InterviewPrepKit

Home / Cheat Sheet / AI Agent System Design

Cheat sheet

Tools and MCP

Read the full lesson →

A tool call is text in, text out: definitions render first in the prompt, the model emits a tool_use block, your code runs it and appends a tool_result — every guarantee lives in the code you write after that edge.

The loop

  • Tool: a function you expose; the model asks by name with arguments, your code runs it, you hand back the answer. The model never runs anything.
  • Harness: your loop — send request, read reply, execute the tool asked for, append result, send again.
  • Three JSON pieces carry it all:
    • Tool definition (schema): name, description (English prose for the model), input_schema (JSON Schema args). Sent in the tools array.
    • tool_use block (comes back): name, chosen input, and id; stop_reason: "tool_use" signals it waits on you.
    • tool_result block (you send next): carries the same tool_use_id, sent with "role": "user" — tool output is input from the world, same standing as a user typing (this is the security basis).
  • Denials and thrown exceptions do not break the loop — both return a tool_result with is_error: true, so the model sees the failure and can react. The error string is the next prompt: make it actionable.

What it is mechanically

  • No function-calling engine — text in, text out the whole way. Definitions serialize into tokens (~4 chars each) placed ahead of the system prompt, billed every turn.
  • Constrained decoding is off by default. strict: true compiles the schema into a grammar and applies logit masking — setting illegal next-tokens to probability zero.
  • Three consequences of definitions rendering first:
    • They sit in the cacheable prefix (position 0). Prompt caching: cached read bills 0.1×, the write 1.25×. Prefix match — one changed byte invalidates everything after, so a per-user tool list kills the cache for everyone.
    • Tool count costs tokens every turn (~150 tok/tool as an order-of-magnitude; count your own).
    • The description is prompt text competing for attention, not registry metadata.

The description decides when

  • Highest-leverage field: description (not schema, not executor) decides whether the tool ever fires. Modern models under-trigger — they reason more, reach for tools less; expect tool-call rate to drop on newer models, recover it with explicit trigger conditions.
  • A strong description has four parts: (1) what, (2) when to call — positive trigger as a condition, with the reason attached, (3) when not to call — the boundary (most often missing), (4) what comes back.
  • Sibling overlap: when two tools could answer the same turn, each description must name the other by exact name and rule itself out. No mutual exclusion = coin flip = test flakiness.
  • Debug “right tool, never used” in order: trigger condition → sibling overlap → system prompt implying the model already knows. Prompt nudging is last.

Tool surface design

  • Any one yes means a dedicated tool; three noes route to bash:
    1. Needs a permission gate?
    2. Needs custom UI, audit trail, or staleness check?
    3. Must the harness know it is parallel-safe?
  • bash hands over an opaque string — the harness can’t gate, render, audit, parallelize, or enforce invariants. Start with bash for breadth; promote an action the moment you need any of the five.
  • Practical rules: 5–15 tools comfortable, accuracy degrades past ~20; one tool one job; enum for closed sets; return structure not prose; truncate loudly; make errors actionable.

Strict — shape, never meaning

  • Default: schema is prose the model usually follows, but the API promises nothing — wrong types, missing required fields, undeclared fields all possible.
  • strict: true enforces declared types, all required present, no undeclared field, valid tool name. Requires additionalProperties: false and a complete required list. Flag sits at top level, next to name, not inside input_schema.
  • Fixes shape, never semantics — a well-shaped call can still refund $5,000 for a nonexistent order. Business validation stays in your harness, always.

Selection vs extraction failures

SymptomDiagnosisFix
Wrong tool chosenSelection — overlapping descriptionsSharpen triggers, state each boundary
Right tool, date="next Tuesday"Extraction — under-specified schemaformat, example in description, strict
Invents a tool nameHallucinated capabilityis_error with real names; audit system prompt
null for a required fieldOptionality ambiguity, no strictReal default, or say what to do when unknown
  • Extraction fix ladder (cheapest first): (1) property description with literal example, (2) enum/format, (3) strict: true, (4) tool-use example in the definition, (5) prompt engineering last. Only 2 and 3 are structural (reach constrained decoding); 2 declares, 3 arms.

Scale (50+ tools)

BranchWho narrowsCostCached prefix
RouterCheap classifier, before the callHand-maintained table that rots silentlyClean
Tool searchThe model, mid-turnOne extra round tripPreserved — schemas appended, not swapped
NamespacingYou, at design timeArgs move out of the schemaClean, but smaller surface
  • Tool search: a built-in tool that finds other tools; defer_loading: True keeps schemas out of context until queried. The search tool never defers and at least one ordinary tool stays loaded. Dated type (e.g. ..._20251119) is a frozen-behavior name, not a rank — pick by feature, not by larger number.
  • server_tool_use = provider ran it on its own infra; no tool_result owed (unlike ordinary tool_use).
  • Namespacing collapses N tools into one action enum — the opposite of “one tool one job.” Trade favors it only when schema volume dominates; if you namespace, re-add the gate by hand inside the handler.

MCP

  • MCP (Model Context Protocol): a published convention for how a provider describes and exposes tools, so one integration works with any client. A wire format, not a broker you deploy — connections stay one per pair. Turns N×M integrations into N+M.
  • Parts: server (separate process wrapping an API), client (speaks MCP to exactly one server), host (your app, one client per server). Client sends initialize, calls tools/list (returns the same three fields you’d write), host splices them into the same tools array; a tool_use routes to the client via tools/call.
  • Transport is a trust boundary: stdio (child process, runs as you, no auth) vs HTTP/SSE (remote endpoint, real auth/multi-tenancy/network). Pin server versions — an update ships new descriptions straight into your prefix.
  • Three primitives by who holds the trigger: Tools (model acts unprompted), Resources (application pulls, gated by your code, don’t self-enter context), Prompts (user invokes deliberately).
  • Security: a third-party server is untrusted input at prefix position 0. Its descriptions are a first-class field, never through your content pipeline, so content-wrapping doesn’t apply — this is prompt injection territory. Pin versions, diff descriptions on update, limit granted authority. MCP doesn’t solve selection-at-scale, authorization, or cost.

Sandboxes, PTC, computer use

  • Sandbox: OS/hypervisor-level isolation (never exec() or RestrictedPython — language-subset jails are escapable via introspection chains). Constraints: no network (allowlist only), ephemeral FS, CPU/mem/wall-clock caps, non-root with dropped caps, return only stdout/stderr/exit code. Fresh container per session, not per call.
  • Programmatic tool calling (PTC): the model writes a script calling your tools as functions inside the sandbox; intermediate payloads stay there, only print output crosses back. Context cost is O(1) in payload size, not O(D). Mark tools callable with allowed_callers naming the exact container type.
  • Computer use: action space is a screen (screenshot, click, type, key, scroll); every turn ships an incompressible image.
    • Image tokens = ceil(width/28) × ceil(height/28) (28×28 px patches; ceilings because a partial edge patch costs a whole one).
    • The token cap bites before the long-edge cap. Current tier (Opus 4.7+): 2,576 px / 4,784 tok, 1080p = 2,691 tok. Standard tier: 1,568 px / 1,568 tok, 1080p downscaled to 1,560 tok — ~1.7× difference; always state the tier.
    • Shrink resolution before trimming old screenshots (trimming breaks the cache). If an API exists, use it — computer use is ~10–50× the cost and less reliable.

Skills and OKF

  • Skill: a folder with a SKILL.md (instructions plus optional scripts/refs). Only the short description sits in context; the body is read on demand via a file-read tool — progressive disclosure, same cost profile as defer_loading. Use for “how we do X here” runbooks (need all of it, once, in order); an API reference is a retrieval problem instead.
  • OKF (Open Knowledge Format): emerging spec for portable, model-agnostic domain knowledge; MCP standardizes actions, OKF aims at knowledge. Early — know the one-liner, don’t over-claim.
Want the full picture? The lesson has the derivations, worked examples, and diagrams this card compresses into bullets. Read the full lesson →
Report a bug