Borrowed Minds: A Model-Call Layer for AI Agents
A small CLI that lets one AI agent call other models and pull their answers back into the session — and the restraint that keeps it useful.
If you do most of your work inside one AI agent (the coding assistant or chat interface you drive all day), that’s where your context lives. But no single model is best at everything, and the usual workaround, copying your work into a second tool for another model’s take, breaks your flow and strands the result in another window.
A model-call layer removes that friction. It’s a small command-line tool that lets your primary agent call other models’ APIs directly and pull their answers back into the session it’s already working in. Your agent stays the orchestrator; other models become functions it can invoke.
The core idea: deliberately dumb plumbing
The discipline that makes this work is restraint. The layer does one thing: take an input, send it to a named model, return the output. It knows nothing about why it’s being called: no logic about when to consult another model, how to weigh competing answers, or what counts as a good result. That judgment stays in the agent driving it. Plumbing stays plumbing.
The moment routing rules or evaluation logic leak into the tool, it stops being reusable and becomes a second brain competing with your first. Keep it dumb and it composes with anything.
What it gives you
- Second opinions on demand. Mid-task, your agent can ask a different model family to check a plan, critique code, or stress-test an argument, then act on the answer without you leaving the room.
- Cross-model evaluation. Run the same prompt through several models and compare. Where strong models disagree is a useful place to look; it often marks the genuinely hard part.
- A stable interface over a churning field. Model names change constantly. Refer to models through aliases (a “cheap” tier, a “reasoning” tier) that map to real IDs in one config file, and your workflows survive every rename and retirement. You update one line.
- Cost awareness by default. Cheap models handle the routine; you spend up to a frontier model only when you ask. Each call returns a best-effort cost estimate, so spending never hides.
How it’s built
Small enough to describe completely:
- One CLI, provider chosen by a flag:
call --provider <name> --model <alias> …. The input, which can be long, arrives over standard input or a file, never as a command-line argument (argv has length and escaping limits). - A thin adapter per provider. This is the one piece of real work. Each provider expects a different request shape: typically a list of role-tagged messages (a system instruction plus your input as the user turn), with its own names for token limits and temperature. The layer normalizes one internal request into each provider’s format. A first version can stay plain text-in/text-out and skip streaming, tool-calling, and image input; add those only when you need them.
- Structured output, always. The tool returns JSON on standard output: the
response text, the exact model ID that answered, token usage, a cost estimate,
and an
ok/error field. Logs and diagnostics stay separate. The agent parses a result and branches reliably on success or failure instead of scraping prose. Reporting the real model ID matters the moment fallbacks exist: the agent needs to know which mind it actually borrowed. - Aliases in a config file. A small file beside the tool maps names like
cheapandreasoningto real model IDs, with a default per provider. This is the churn-isolation layer. - Secrets only from the environment. API keys are read from environment variables, never written into the code, the config, logs, or any output. A missing key returns a clean, named error, not a crash.
- Resilience you can reason about. Transient failures (rate limits, overloads) retry with backoff; you decide which errors are retryable and which are fatal. An alias may name a fallback model so a busy primary degrades to a working one. Because the output reports which model answered, a degraded answer is never silent. Give each call a timeout so a slow provider can’t stall the agent.
A compact picture of the contract:
$ echo "Review this plan for risks." | call --provider openai --model reasoning
{ "ok": true, "model": "<resolved-id>", "output": "…",
"usage": { "input_tokens": 0, "output_tokens": 0 }, "cost_estimate_usd": 0.01 }
Two things to respect
Whatever you send, leaves. The input goes to a third-party API. Keep secrets and sensitive material out of what you pass, and know each provider’s data-use terms.
Treat the answer as untrusted. Another model’s output is text from outside your system. Before your agent acts on it, remember it can carry instructions of its own; don’t wire it straight into commands unreviewed.
Why it’s worth building
Consulting another mind stops being a context-switch and becomes a reflex. When a second opinion costs one command and pennies, you ask for it far more often, and work you would have shipped unchecked gets a second pass it otherwise wouldn’t.
One constraint is worth keeping on purpose: trigger each call yourself, in real time, rather than letting the layer run unattended on a schedule. The point is to put another model within your agent’s reach, not to start an autonomous system humming in the background.
The engraving above was generated by Google’s Gemini (Nano Banana Pro), prompted through the very kind of cross-model call this essay describes — the piece illustrating itself.