---
slug: compound-tools-vs-programmatic-tool-calling
title: "Compound tools vs programmatic tool calling: what was built, what was meant, and the side-by-side"
kind: article
status: published
hash: bc9c3c0bfac95d188afa9b355bba8196075d1dfd63ed6140ddfa4738389a6921
created: 2026-10-08T20:31:47.633Z
updated: 2026-10-09T06:28:55.309Z
summary: ""
tags: []
above: []
below: []
adjacent: []
nested: []
---
# Compound tools vs programmatic tool calling: what was built, what was meant, and the side-by-side

The owner asked for compound tools: single tools the models hold, whose arguments carry sub-commands and **complications** — modifiers that shape the call, like `code + grep = true`, or a full REST call with headers and options inside one tool. What the models resolved on, working with Claude and Codex on 2026-10-05, was the **CODE** tool. This article spells out what they built, compares it honestly with industry programmatic tool calling, and then answers four questions the owner raised that the models never addressed.

---

## 1. What the models resolved on: CODE, as built (verified from the live contract)

CODE is one tool, in the Directory, with 11 operations and 30 invocation methods:

`schema · grep · read · edit · write · check · grammar · deploy · ship · job · result`

Its defining properties, from the deployed description:

- **Hash-checked canonical writes** — an edit against a stale hash is refused, not applied. The runtime owns truth.
- **Detached tests and deploys** — tests and ships run as jobs; the call returns a job id and receipts, not a blocked session.
- **Response budgeting** — every call carries `return: {select, max_bytes, mode}` so the model states *what it wants back* instead of receiving a warehouse. This is a complication, in the owner's sense — the models built one without naming it that.
- **Deterministic operations; no model planner** — the runtime does all mechanics. The model never writes code, never sees a shell.

Evidence it works: 399 CODE calls on the Ledger (2026-10-05, run by Agent 4 Code Mode on connected build env-4), each with a receipt, tests executed detached (`steps:[{name:"tests", exit:0}]`), full results stored in R2 (`coding/results/<job-id>.json`).

---

## 2. Industry programmatic tool calling (PTC)

The industry pattern (Anthropic's code-execution-with-MCP, OpenAI's code interpreter, and the MCP ecosystem generally): the model **writes code** that calls tools or APIs, a sandbox executes it, results flow back to the model. Variants differ in where the sandbox sits; the constant is **the model is the programmer**.

Properties: arbitrary logic (loops, conditionals, joins), full expressiveness — and full exposure: the model can do anything the sandbox allows, every iteration costs model tokens, code must be generated and debugged, a sandbox is required, and evidence of what ran is whatever the model chooses to log.

---

## 3. Side by side

| | **Industry PTC** | **CODE as built** | **Owner's compound-tool vision** |
|---|---|---|---|
| Who writes the logic | The model, in code | Nobody — the runtime already encodes it | Nobody — declared through complications |
| Model's job | Program + debug + interpret | Choose op + arguments | Choose tool + command + complications |
| Determinism | None — model code does anything | Total — hash-checked, gated, receipted | Total — runtime compiles the declaration |
| Cost per action | Model tokens per iteration of code generation | ~One small structured call | ~One small structured call |
| Sandbox needed | Yes | No | No |
| Coverage | Anything code can do | Coding on one build | Whole API surfaces (REST, search, computer, Mac) |
| Failure mode | Buggy model code, runaway loops | Refusal on stale hash (safe) | Mis-stated complication (safe) |
| Evidence | What the model logs | Automatic: receipt + Ledger rows + R2 results | Automatic, same mechanism |
| Fits novel algorithms | Yes | No | Only if complications cover it |

The honest ruling: PTC and compound tools are **opposites in exactly the way the owner says**. PTC pushes intelligence into generated code; compound tools pull mechanics out of the model into a declared, bounded contract. PTC is the right tool when the logic is genuinely novel. Compound tools are the right tool when the surface is known — which is most of what agents do.

---

## 4. The owner's vision, formalized: one tool per domain, complications in the arguments

The models narrowed the idea to a coding tool. The owner's idea is a **pattern**. One tool per domain, whose argument object carries a command and complications that the runtime compiles into the real call:

**REST — one tool for every HTTP API, including Google Calendar:**

```
REST {
  api: "google.calendar",
  command: "events.insert",
  body: { calendarId: "primary", ... },
  complications: {
    headers: { "If-Match": "..." },      // full header control
    query: { maxResults: 10, orderBy: "startTime" },
    auth: "google",                      // runtime picks the stored grant
    retry: { on: [429, 503], backoff: "exp" },
    return: { select: ["id", "htmlLink"], max_bytes: 2000 }
  }
}
```

The model never hand-assembles URLs, auth headers, pagination or error handling. The runtime holds the API's contract; the complications shape it. Compare the industry path today: N separate MCP tools per API (each costing tool-definition tokens in every prompt), or PTC (the model writes fetch code and debugs its own headers).

**SEARCH — domestic first, then escalation, by complication:**

```
SEARCH { q: "...", complications: { escalate: [directory, ledger, web, apis], max_bytes: 4000 } }
```

Today's `misc_find` searches only the Directory. The owner's point is correct and the current design is wrong: a search tool that fails silently when the answer is on the web or in another API is a dead end. Escalation should be a complication of the one tool, not a separate tool the model must remember exists. (Live proof of the gap: the build's own web-search capability died this session with `NO_MORE_CREDITS` and nothing escalated.)

**MAC / COMPUTER — one atomic tool for the whole machine:**

```
COMPUTER { surface: shell | applescript | alfred | ax | keychain | gui, command: ..., complications: { cwd, timeout, evidence: "full" } }
```

Today this exists as five scattered tools (LOCAL_EXEC, LOCAL_WRITE, LOCAL_PS, CLI_CLAUDE_CODE, plus unexposed AppleScript). One atomic tool with a `surface` complication is the same pattern as REST: one contract, the runtime compiles per-surface.

**Is an atomic computer-use tool more efficient than industry computer use? Yes, measured in the only currency that matters to a model — tokens and determinism.** Industry GUI computer use (screenshots + click coordinates) costs roughly 1,000–2,000 tokens per step (each screenshot), is probabilistic (wrong pixel, missed menu), and slow (seconds per action). The atomic tool does the same work through shell/AppleScript/AX at ~50–200 tokens per action, deterministically, with receipts. Screenshots are for *verification* — a complication (`evidence: screenshot`), not the primary channel. The efficient pattern: the model declares intent over structured surfaces, and pixels are only requested when the structured surface cannot answer.

---

## 5. SQL: the models were ignoring efficiency and boundedness — measured

The owner's concern is not hypothetical. From this build's own `pg_stat_statements`, before today's fixes:

- One task-window query ran **227 times at 19,600 ms each** — ~74 minutes of database time — because it wrapped an indexable column in `COALESCE()` and regex-scanned an 8 GB table with no LIMIT.
- `?tool=CODE` from the Ledger API timed out outright (no index).
- The SQL door had **no statement timeout and no row cap**: any model, on any task, could issue an unbounded scan.

Fixed today: three indexes added (`ledger_tool`, `ledger_task_ops`, `ledger_model`), the COALESCE wrappers removed (deployed commit `90fa5ae`), the worst query now 189 ms (~100x). Still owed, and now specified: the SQL door should enforce `statement_timeout` (e.g. 15s), a hard row cap unless a complication raises it, and `EXPLAIN` cost checks — because bounded queries are a runtime guarantee, not something to hope the model remembers. The compound-tool pattern applies here too: `SQL { q, complications: { timeout_s, max_rows, explain_first } }`.

---

## 6. Ruling

1. The models got the **structure** right (one tool, ops, budgeted returns — the complication seed is already inside CODE's `return` field) and got the **scope** wrong: they froze the pattern onto coding instead of building it as the general shape for REST, SEARCH, COMPUTER and MAC.
2. PTC is not the competitor to that; it is the **fallback** for novel logic that complications cannot express. Every compound tool should be able to say "this surface is fully covered — do not write code." Every PTC capability should be audited for whether it has become a complication.
3. Order of work: SEARCH escalation (smallest, highest value), MAC unification, REST with the Google surface first, COMPUTER last (needs the surfaces audited). SQL guardrails are a 20-line change to the sub-workers door and should ship with the next deploy.

Everything cited here was measured on 2026-10-08: the CODE contract from `GET /api/tools/CODE`, the 399 calls from the Ledger, the SQL timings from `pg_stat_statements` and EXPLAIN ANALYZE via the build's SQL door.
