PATTERN Cited by 1 source
Tool-call loop minimal agent¶
Pattern¶
A tool-using LLM agent is, in its simplest form, a single function that appends to a context array and calls one LLM endpoint in a loop:
- Append the user message to
context. - Call the LLM with
context+ a list oftools(each tool is a JSON schema describing name, description, parameters). - If the response contains one or more
function_callitems: for each, run the tool, append the tool's output as afunction_call_outputtocontext, and loop back to step 2. - Otherwise, append the assistant text to
contextand return it.
Fly.io demonstrates this in ~30 lines of Python against the
OpenAI Responses API — call(tools) wraps
client.responses.create, tool_call(item) runs one tool and
returns its input+output pair, handle_tools(...) iterates the
response's function-call items, and process(line) drives the
loop. The "agent" is that code. (Source:
sources/2025-11-06-flyio-you-should-write-an-agent.)
"Did you notice where I wrote the loop in this agent to go find and ping multiple Google properties? Yeah, neither did I. All we did is give the LLM permission to ping stuff, and it figured out the rest."
Why it matters¶
Three things the minimal loop makes visible:
- Multi-step planning is emergent. Fly.io's demo asks "describe
our connectivity to google" and the LLM independently issues
three separate
pingtool calls (google.com,www.google.com,8.8.8.8). The agent author never wrote a "ping multiple endpoints" loop; the LLM decomposed the task against the available tools and the loop re-enteredcall()until the LLM was ready to produce a final answer. Tool inventory + a loop is the whole planner. - No MCP required. Fly.io explicitly notes the minimal agent needs no MCP: "MCP isn't a fundamental enabling technology. […] MCP is just a plugin interface for Claude Code and Cursor, a way of getting your own tools into code you don't control. Write your own agent. Be a programmer. Deal in APIs, not plugins." MCP becomes valuable precisely when you want your tools consumable by an agent someone else built; for your own agent, native tool-schema JSON is enough.
- ~10 minutes of bash makes a coding agent. "Spoiler: you'd
be surprisingly close to having a working coding agent. Imagine
what it'll do if you give it
bash. You could find out in less than 10 minutes." This is the structural reason agent ecosystems exploded in 2024–2025: the barrier to a working prototype is small.
Building-block variations (cheap to iterate)¶
Once the minimal loop is working, Fly.io points at the space of useful variations — each "your wackiest idea will probably (1) work and (2) take 30 minutes to code."
- Sub-agents. Spawn a second context array + LLM call with its own tools (concepts/sub-agent + patterns/context-segregated-sub-agents).
- Summarise old context. Feed a slice of the array back through the LLM and splice the summary back in as compression (concepts/context-engineering).
- Tree-of-agents. Build parent/child chains, each sub-agent specialised by tool allowlist.
- Multiple personalities. Two context arrays sharing the same user line, routed by coin-flip — the Fly.io Alph / Ralph demo.
- Persist context. Dump the array to SQLite between process runs; reload on next start (systems/sqlite).
- Swap tool allowlists per phase. Planning phase has the wide tool surface; execution phase has narrow tools so schemas don't crowd out output tokens (patterns/tool-surface-minimization).
When to reach for MCP vs. this pattern¶
Use this minimal-loop pattern when:
- You own both the agent and the tools.
- You want tight control over context allocation, tool schemas, retries, and cost accounting.
- You're prototyping a new agent shape.
Reach for MCP (patterns/wrap-cli-as-mcp-server) when:
- The consumer is an agent someone else built (Claude Code, Cursor, Goose, Claude Desktop).
- You want the same tool server to serve multiple agent clients with one integration.
Fly.io's posture: "When you read a security horror story about MCP your first question should be why MCP showed up at all." The claim is not "MCP is bad" — it's "if you control the agent, you probably didn't need it; write the agent."
Caveats¶
- The minimal loop has no turn-budget cap; a misbehaving LLM can loop on tool calls indefinitely. Production loops bound iteration count.
- Tool outputs go into context verbatim by default. Large outputs consume token budget for the rest of the session — production agents truncate, summarise, or store-and-reference.
- Security segregation is the operator's responsibility. Fly.io notes "You can trivially build an agent with segregated contexts, each with specific tools. That makes LLM security interesting." The minimal loop as written has one context and one tool set; production security posture requires splitting.
Seen in¶
- Fly.io, You Should Write An Agent (2025-11-06) — canonical ~30-LoC Python demonstration of the pattern + the "ping connectivity to google" emergent-planning demo. (Source: sources/2025-11-06-flyio-you-should-write-an-agent.)
- Fly.io flymcp (2025-04-10) — 90-LoC Go MCP server wrapping
flyctluses the same loop shape one level up; tool output structured by--json(patterns/wrap-cli-as-mcp-server).