dllama.tech · Knowledge Course KC 101-05
KC 101 · Foundations — Unit 05

Tools & function calling

~12 min read · Written 2026-08-30 · Research: Mara · Slug tools-function-calling

Summary

A language model, left alone, can only emit text. Function calling turns that text into actions: the model receives a list of tool schemas, decides one fits the request, and emits a structured call — JSON naming the tool and its arguments. The runtime — not the model — executes the call and feeds the result back as a new message. That round trip, repeated, is the agent loop — the single unit of agency everything else in this course builds on.

The tool call is a contract between the model and the runtime. The schema says what arguments are legal; the description tells the model when to reach for the tool. Parallel calls let the model batch independent work in one turn. The failure modes are all about the contract breaking — malformed JSON, hallucinated arguments, results too big for the context window, stuck retry loops — and each one is the runtime’s problem to catch and the schema designer’s problem to prevent.

Two architectures get models to act. Native function calling is a trained capability: the model emits structured, schema-validated calls the API returns as data. Code-writing is the generalist path: the model emits Python or shell and a sandbox runs it. Native calling is safer and cheaper to validate; code is more flexible. Everything in Mo’s stack — Hermes’ tool loop, his MCP servers, Claude Code, DeepSeek’s OpenAI-compatible API — is one of these two.

AudienceSomeone who runs an agent stack daily and wants the layer under it.

KC 101 · Foundations · Status: published

Call01Function calling — the model requests, the runtime acts

The mental model that makes everything else obvious: the model never executes anything. It has no hands. It is a next-token generator trained, on top of plain language modeling, to do one additional thing: when a request can be satisfied by an available tool, emit a special structured block naming the tool and its arguments. Then the model stops — the runtime parses the block, runs the function, and returns the output as a new message, after which the model continues.

A minimal example, in the format DeepSeek’s API and OpenAI’s API both use:

Example — what the model emits
{
  "type": "function",
  "function": {
    "name": "get_quote",
    "arguments": "{\"symbol\": \"AAPL\"}"
  }
}

The arguments are themselves a JSON string — the outer call is structured, but the payload inside is still text the runtime must parse. This is exactly how Anthropic describes it: the model “returns a structured call that your application executes” — your application, not the model.

Jargon translation
Function calling / tool use / tool calling — three names for the same thing. OpenAI’s docs call it function calling; Anthropic’s call it tool use (“Tool use (also called function calling) lets Claude call functions that you define”); MCP calls the same objects “tools”. A tool is just a function with a name, a description, and a parameter schema that the model can see.
In practice — DeepSeek (Mo’s own API)

DeepSeek’s API is OpenAI-compatible: the request carries a tools array with type: "function" and a function: {name, description, parameters} object; the response carries a tool_calls array when the model decides to act. The same call shape works whether the model is DeepSeek V4 Flash on Mo’s own key or a hosted frontier model — which is why Hermes can route the same agent session across providers without changing the tool layer.

The separation to hold onto: the provider’s API defines the wire format; the runtime (Hermes) defines what the tools do.

Result02The tool-use loop — the unit of agency

An agent is not a model; an agent is a loop. One iteration:

Fig. 1 — One tool round trip
  1. 01RuntimeThe runtime assembles the context: system prompt, tool schemas, history.
  2. 02ModelThe model replies with text (done) or emits one or more tool calls.
  3. 03RuntimeThe runtime executes each call and appends the results as new messages.
  4. 04LoopBack to step 1, until the model replies without tool calls.

Each pass through steps 1–4 is one tool round trip, and a task is usually several. Watch what that implies for the context window (101-02): every round trip appends the call and the result to the conversation. A ten-step task means ten more chunks of context — tool output is tokens, and tokens are budget.

Two properties make the loop an agent rather than a chat: conditionality (the model chooses, turn by turn, whether to call a tool at all) and feedback (the result is new information the model genuinely did not have). Without feedback, a tool call is theater; with it, the model’s next decision is grounded in the real world.

In practice — Hermes

Hermes’ agent loop is exactly this. Every capability — read_file, terminal, search_files, patch, web_search, browser_exec, image_generate, skill_view, delegate_task — is a tool with a name, a description, and a JSON parameter schema in the system prompt. When Hermes acts, the transcript shows a tool call followed by a tool_result message, and the model reasons over that result before its next move. Policy layers sit between model and execution: approvals and deny rules for dangerous tools, truncation for big outputs, sandboxed execution.

That separation — model proposes, policy disposes, runtime executes — is the difference between a demo and a system you let touch your files.

Call03Schemas — the contract between model and machine

For the model to call a tool, it must know what the tool is called, what it does, and what arguments it takes. That is the schema:

Example — the tool schema the model sees
{
  "name": "get_quote",
  "description": "Get a live stock quote for a ticker symbol",
  "parameters": {
    "type": "object",
    "properties": {
      "symbol": {"type": "string", "description": "Ticker, e.g. AAPL"}
    },
    "required": ["symbol"]
  }
}

Three parts, three lessons:

  • The name is the handle the model emits. Names read like code (get_quote, not “fetch me the number for a stock please”) because the model must reproduce them exactly.
  • The description is advertising copy. The model chooses tools by matching the request against descriptions — Anthropic: “Claude determines when to call a tool based on the user’s request and the tool’s description.” A vague description means the tool never gets called; an overpromising one means it gets called for the wrong jobs.
  • The parameters are a JSON Schema — types, enums, required fields — which is what the runtime validates the call against before executing.
In practice — MCP (Mo’s servers)

MCP — the Model Context Protocol — is the standardization of this contract across tool ecosystems. The spec defines a tool as three fields — name, description, inputSchema (a JSON Schema) — exposed over JSON-RPC so any MCP-capable client can discover and call them: “Tools enable models to interact with external systems, such as querying databases, calling APIs, or performing computations.”

Hermes registers each connected server’s tools into its own namespace — hence Mo’s mcp__fmp__getQuote, mcp__design_inspiration__design_search_styles, mcp__open_design__create_artifact: FMP, design-inspiration, and Open Design all speak the same contract and look like native tools to the model. The win is portability — any MCP client can drive any MCP server (201-04 in depth). The cost: a server with ~255 tools (FMP’s catalog) can’t all fit in context — a live problem the field is solving (Anthropic’s Tool Search) and a preview of 301-02’s caching economics.

Result04Why tools are what turn a chatbot into an agent

A model without tools is an oracle: it can answer, argue, and predict, but it cannot do — cannot read your files, run your commands, fetch today’s prices, or edit your code. Add tools, and two things change at once.

First, the model gains hands on the world. It can run terminal, edit a file, search the web, query a database. Anthropic’s tool-use GA announcement: “Tool use, which enables Claude to interact with external tools and APIs,” lets it “perform tasks, manipulate data, and provide more dynamic — and accurate — responses.”

Second — less obvious and just as important — tools are the model’s only source of fresh ground truth. Every fact the model “knows” from training can be stale or wrong (101-06’s whole subject). A tool result is new information, fetched at the moment of use: when Hermes answers “what is the current price of X,” it calls the FMP MCP tool and reads the result rather than trusting its weights. That is grounding in its purest form — the loop forces the model to argue from evidence it just obtained.

Key idea

So the definition falls out cleanly: an agent is a model plus tools plus a loop that runs them. No tools, no agent — just chat. 201-01’s agent loop, 201-02’s delegation, and 301-07’s security all assume this mechanism exists.

In practice — Claude Code

Claude Code is the same loop wearing a CLI. Its built-in tools — Bash, Read, Edit, Grep, Glob, WebFetch, TodoWrite, plus MCP servers and subagents — are schemas presented to Claude, which drives them in exactly the loop above: read a file, edit, run a test, read the output, iterate. Anthropic’s tutorial walks from “a single tool call” to “a production-ready agentic loop” — this lecture is that tutorial’s theory.

Call05Parallel tool calls — one turn, many tools

The loop as described is serial: one call, one result, one decision. But modern models — OpenAI, Anthropic, DeepSeek’s API — can emit multiple tool calls in a single turn; the runtime executes them concurrently and returns the results in order. Three tickers, two files, two queries — one round trip instead of six.

Key idea

The rule of thumb that keeps this sane: parallelize reads, serialize writes. Fetching five quotes in parallel is free and safe; running five file edits or shell commands whose outputs might interact is not — results can race and side effects collide.

The model structures its calls accordingly: independent work in parallel batches, dependent work in sequential turns. Runtimes keep it straight by feeding results back in call order, so the model always knows which answer belongs to which call.

In practice — Hermes

Hermes’ system prompt encodes the pattern explicitly: when several pieces of information don’t depend on each other, request them together in a single response so they execute concurrently — serialize only when a later call depends on an earlier one’s result. You see it whenever a Hermes turn fires three web_search calls at once or reads two files in one batch. That batching is not cosmetic: it cuts wall-clock time per round trip and keeps the loop’s context smaller than the serial version.

Result06Failure modes — where the contract breaks

Tool use fails in four characteristic ways, and recognizing them is most of debugging agents:

  1. Malformed JSON. The model is a token predictor; occasionally it emits a call the parser cannot read — unclosed braces, truncated arguments, a stray markdown fence. Modern APIs mitigate with constrained decoding and structured outputs (the model can only emit valid JSON); runtimes retry or ask the model to fix itself. If you’re seeing parse errors, the model or the schema is the problem, not the parser.
  2. Wrong arguments. The JSON is valid; the values are wrong — a hallucinated file path, a ticker that doesn’t exist, a required field omitted. Validation catches missing fields; nothing catches semantically wrong ones. read_file on a path the model invented is a wrong-arg failure, and the fix is usually “search for the file first” — more tool calls, not fewer.
  3. Results too big. The worst failure, because it is silent. A terminal dump or a 10,000-line file read can blow the context budget and push the session toward compaction (101-02). Runtimes truncate — Hermes caps large reads at ~100K characters and returns a continuation offset; Anthropic’s programmatic tool calling keeps intermediate results out of context entirely. The lesson: tool output is context, and context is a budget.
  4. Failing tools and loops. A tool can fail for reasons the model cannot see — network errors, permissions, timeouts. A well-built runtime feeds the error back (exit code, stderr) and lets the model adapt; a badly built one lets it retry the identical call forever. An agent thrashing on the same failing command is not the model being dumb — it is the loop missing a guardrail (retry caps, error feedback, denial rules) the runtime should provide.
In practice — Claude Code

A failing Bash command’s nonzero exit and stderr are returned to Claude as tool output, so the model reads the actual error and changes strategy; same for Edit failures and WebFetch timeouts. The rule to steal: never swallow tool errors — the model can only adapt to what it can see.

Call07Native function calling vs. “the model just writes code”

There are two fundamentally different ways to get a model to act, and knowing which one you’re looking at tells you how to trust it.

Native function calling is a trained capability: the model was fine-tuned on tool-call traces until emitting tool_calls is as natural as prose. The call is structured by construction — the API returns it as data, not text to parse — and validated against the schema before executing. Costs: you must declare every tool up front, schemas eat context, and the model can only do what you declared.

The model just writes code is the generalist path: give the model a shell (Bash in Claude Code, terminal in Hermes) and let it emit Python or shell as its “tool call.” Nothing to declare, nothing to validate — the model can do anything the sandbox can do. Costs: arbitrary code is arbitrary risk (sandboxing becomes mandatory, see 301-07), output is less predictable, and the model can burn tokens generating a loop you’d rather it had made in one structured call.

The pattern in real stacks is both, deliberately: structured calls for known, repeated, high-stakes operations (MCP tools, file edits, API calls — validated, auditable, cheap); code execution for novel, exploratory work (computing, transforming data, gluing things together).

Gotcha

There is also a fragile third way — prompting “output JSON” and parsing the prose — what people do with models lacking native function calling. It works until the model wraps the JSON in a markdown fence and your parser dies; native calling exists precisely to retire that hack.

In practice — the stack

Hermes’ tool layer is native function calling — every capability and every MCP server tool is a declared schema — with terminal as the code-execution escape hatch. Claude Code is the same split: Read / Edit / Grep are structured; Bash is arbitrary code. DeepSeek V4 Flash on Mo’s own key supports the same OpenAI-compatible tool-calling format — which is why Hermes can run agent loops on it at all: a model without native function calling can’t participate in this course’s loop (you’d be back to the JSON-in-prose hack).

When someone says “the model decided to call a tool,” one of these two mechanisms fired. Now you can tell which.

Result08Key takeaway

Key idea

Function calling is the contract that turns text into action: the model proposes structured calls, the runtime executes them, and the results feed back into the loop. Tools are what make a chatbot an agent — they give the model hands on the world and its only source of fresh ground truth.

Native function calling (declared schemas, validated calls) and code-writing (arbitrary sandboxed execution) are the two mechanisms underneath every agent you run, and the failure modes — bad JSON, bad args, oversized results, stuck loops — are all contract violations the runtime must catch and the schema design must prevent.

Call09Go deeper

Top references (free)
  1. [1]

    Anthropic — “Tool use with Claude” (platform.claude.com)

    https://platform.claude.com/docs/en/agents-and-tools/tool-use/overview

    The canonical definition (“Claude determines when to call a tool based on the user’s request and the tool’s description… returns a structured call that your application executes”), the full loop, and the tutorial to a production agentic loop.

  2. [2]

    OpenAI — Function calling guide

    https://platform.openai.com/docs/guides/function-calling

    The tools parameter, JSON Schema definitions, parallel function calls, and structured outputs.

  3. [3]

    MCP Specification — Tools (modelcontextprotocol.io)

    https://modelcontextprotocol.io/specification/2025-11-25/basic

    The name / description / inputSchema contract, JSON-RPC transport, and how tools are exposed and called across servers.

  4. [4]

    Anthropic — “Introducing advanced tool use” (engineering post, free)

    https://www.anthropic.com/engineering/advanced-tool-use

    Tool Search (thousands of tools without consuming context) and programmatic tool calling (code-execution orchestration) — where this unit is heading.

Tool-specific docs
  • DeepSeek API (api-docs.deepseek.com)

    https://api-docs.deepseek.com

    OpenAI/Anthropic-compatible API; tools/tool_calls in the OpenAI format on Mo’s own key, models deepseek-v4-flash / deepseek-v4-pro.

  • Hermes — developer guide

    https://hermes-agent.nousresearch.com/docs

    The tool system: native tools + MCP registration, approvals and deny rules, parallel calls, output truncation.

  • Claude Code docs (docs.claude.com)

    https://docs.claude.com/en/docs/claude-code

    Built-in tools (Bash, Read, Edit, Grep, Glob, WebFetch), MCP support, and permission modes.

Research: MaraDesign: Kyra + Open DesignPowered by Hermes Agent