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

Tools & function calling

~9 min read · Written · Research: Mara · Slug tools-function-calling

Summary

Function calling turns a model's text into actions. The model gets tool schemas, picks one that fits, and emits a structured call: JSON naming the tool and its arguments. The runtime, not the model, runs it and returns the result as a new message. That repeated round trip is the agent loop — the unit of agency the rest of this course builds on.

The tool call is a contract between model and runtime. The schema says which arguments are legal; the description tells the model when to reach for the tool. Parallel calls batch independent work in one turn. Failure modes are contract breaks: malformed JSON, hallucinated arguments, results too big for the context window, stuck retry loops. The runtime must catch each; the schema must prevent it.

Two architectures get models to act. Native function calling is trained: 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 the two.

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

KC 101 · Foundations · Status: published

Call→01Function calling — the model requests, the runtime acts

The model never executes anything. It is a next-token generator trained, on top of plain language modeling, to do one extra thing.

When a tool can satisfy a request, it emits a structured block naming the tool and its arguments, then stops. The runtime parses the block, runs the function, and returns the output as a new message. The model continues.

A minimal example, in the format DeepSeek and OpenAI 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. Anthropic says the same: 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 a function with a name, a description, and a parameter schema 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 shape works for DeepSeek V4 Flash on Mo’s own key or a hosted frontier model. That is why Hermes can route one session across providers without changing the tool layer.

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

Result←02The 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. 01Runtime→The runtime assembles the context: system prompt, tool schemas, history.
  2. 02Model→The model replies with text (done) or emits one or more tool calls.
  3. 03Runtime←The runtime executes each call and appends the results as new messages.
  4. 04Loop←Back to step 1, until the model replies without tool calls.

Each pass through steps 1–4 is one tool round trip; a task is usually several. Every round trip appends the call and its result to the conversation (101-02). 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. Feedback: the result is new information the model did not have. Without it, the next decision is grounded in nothing.

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 the model reasons over before its next move. Policy layers sit between model and execution: approvals and deny rules, output truncation, sandboxing.

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

Call→03Schemas — the contract between model and machine

To call a tool, the model must know its name, 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 picks tools by matching the request against the description. Anthropic: “Claude determines when to call a tool based on the user’s request and the tool’s description.” A vague one never gets called; an overpromising one gets called for the wrong jobs.
  • The parameters are a JSON Schema — types, enums, required fields — which the runtime validates the call against before executing.
In practice — MCP (Mo’s servers)

MCP (the Model Context Protocol) standardizes this contract across tool ecosystems. The spec defines a tool as three fields — name, description, inputSchema (a JSON Schema) — over JSON-RPC. 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, and 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) cannot all fit in context. That is a live problem the field is solving (Anthropic’s Tool Search) and a preview of 301-02’s caching economics.

Result←04Why tools are what turn a chatbot into an agent

A model without tools can answer and predict, but it cannot do. It 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, tools are the model’s only source of fresh ground truth. Any fact the model “knows” from training can be stale or wrong (101-06’s whole subject). A tool result is fetched at the moment of use. Hermes answers “what is the current price of X” by calling the FMP MCP tool, not by trusting its weights. That is grounding in its purest form: it argues from evidence 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. It 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.”

Call→05Parallel 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 — emit multiple tool calls in one turn. The runtime runs 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: 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.

Runtimes feed results back in call order, so the model knows which answer belongs to which call.

In practice — Hermes

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

Result←06Failure modes — where the contract breaks

Tool use fails in four characteristic ways. Recognizing them is most of debugging agents:

  1. Malformed JSON. The model is a token predictor, so it occasionally emits a call the parser cannot read: unclosed braces, truncated arguments, a stray markdown fence. Constrained decoding and structured outputs make it emit only valid JSON. Runtimes retry or ask the model to fix itself. If you see parse errors, the model or the schema is at fault, 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. 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) so the model can adapt. A bad one lets it retry the identical call forever. An agent thrashing on a failing command is not the model being dumb; the loop is missing a guardrail: retry caps, error feedback, denial rules.
In practice — Claude Code

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

Call→07Native function calling vs. “the model just writes code”

Two fundamentally different ways get a model to act. 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 API returns the call as structured data, not text to parse, and validates it 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 it 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: it can do anything the sandbox can. 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 one structured call would have avoided.

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

Gotcha

There is also a fragile third way: prompting “output JSON” and parsing the prose. That is 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 format. That 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.

Result←08Key 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 under every agent you run. The failure modes — bad JSON, bad args, oversized results, stuck loops — are contract violations the runtime must catch and the schema must prevent.

Call→09Go 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//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