Provider dialects: same concepts, different field names

Lesson 4 of 5 in Function Calling Deep Dive: The Wire Under Tool Use.

Every dialect encodes the same five things: a tool declaration, a call, an id, a result, and an error signal. What changes between them is spelling and nesting — whether the declaration is wrapped in an extra function object, whether arguments arrive as a string or a parsed object, whether the result is its own message role or a content block inside a user message, whether errors are a boolean flag or a convention in the text.

That is genuinely good news for you: port the concepts, not the code. If you can name which of the five things a payload is showing you, you can read a dialect you have never seen before.

OpenAI-style

Declaration — a tool is a typed wrapper around a function object, and the schema key is parameters:

{ "type": "function",
  "function": { "name": "search_orders", "description": "…", "parameters": { "type": "object", "properties": {} } } }

Call — an array on the assistant message, arguments as a JSON string:

{ "id": "call_7Kq2", "type": "function",
  "function": { "name": "search_orders", "arguments": "{\"customer_id\":\"CUS-40118822\"}" } }

Result — its own message role, correlated by the call id:

{ "role": "tool", "tool_call_id": "call_7Kq2", "content": "3 open orders: …" }

Errors — no dedicated flag in this family historically; you put the error text in content and the model reads it as the result. That works, and it means your wording is the error contract.

Watch out: this vendor’s newer API generation renames and re-nests several of these fields. Same five concepts, different keys.

Anthropic-style

Declaration — flat, with the schema under input_schema:

{ "name": "search_orders", "description": "…",
  "input_schema": { "type": "object", "properties": {} } }

Call — a content block inside the assistant message, with arguments as an already-parsed object under input:

{ "type": "tool_use", "id": "toolu_01A…", "name": "search_orders",
  "input": { "customer_id": "CUS-40118822" } }

Result — a content block in the next user message, not a separate role:

{ "type": "tool_result", "tool_use_id": "toolu_01A…",
  "content": "3 open orders: …", "is_error": false }

Errors — an explicit boolean on the result block.

The parsed-object detail is the one that bites when porting: your OpenAI-shaped code called JSON.parse, and here that would throw on an object. The validation obligation is identical in both — something already turned tokens into a structure, and nothing has yet checked that the structure is legal or permitted.

MCP (specified, not sketched)

MCP is a protocol between your application and a tool server, sitting one layer below the model API — and because it is specified, these names are quotable.

Declarationtools/list returns definitions with a name (unique per server), optional title and icons, a description, an inputSchema (JSON Schema, defaulting to draft 2020-12 when no $schema is present), an optional outputSchema, and optional annotations.

Calltools/call with name and arguments, carried over JSON-RPC 2.0.

Result — unstructured content blocks (text, image, audio, resource links, embedded resources) and/or structuredContent, a JSON value that MUST conform to outputSchema when one is declared.

Errors — protocol errors as JSON-RPC errors; tool execution errors as isError: true inside the result.

Two ids, two jobs: the JSON-RPC id correlates your request with the server’s response, while the model-facing tool-call id correlates the model’s request with the result you feed back. A host bridging model API to MCP server is translating between them.

The framework layer

Frameworks hide all of the above. You annotate a function — a decorator, a typed signature, a docstring — and the framework generates the schema, dispatches the call, and normalises dialect differences behind one interface. Pydantic AI leans on Python types for exactly this; the Vercel AI SDK sells itself as a provider-agnostic TypeScript toolkit; Strands positions itself as “build an agent harness and control it end-to-end”.

Use them. They remove real drudgery and they are usually right about the wire.

Then know where the abstraction leaks, because you will meet all four: schema generation (what did your type hints actually emit for that union type?), error mapping (did a raised exception become a readable tool result, or did it kill the turn?), parallel calls (does the framework fan out, and with what timeout?), and retries (is it silently re-calling a non-idempotent tool?). Every one of those questions is answered by looking at the messages on the wire — which is why this lesson exists inside a framework-heavy world.

The five concepts across dialects — vendor columns are illustrative sketches as of September 2026; the MCP column is spec-defined
ConceptOpenAI-style (sketch)Anthropic-style (sketch)MCP 2026-07-28 (specified)

Where the schema goes

function.parameters, inside a type: "function" wrapper

input_schema, on a flat tool object

inputSchema, plus an optional outputSchema for results

The call itself

An entry in tool_calls on the assistant message

A tool_use content block in the assistant message

A tools/call request over JSON-RPC 2.0

Arguments payload

A JSON string you must parse

A parsed object under input

An arguments object in the request params

Correlation id

id on the call, echoed as tool_call_id

id on the block, echoed as tool_use_id

JSON-RPC request id (transport-level), distinct from the model-facing call id

Result carrier

A message with role: "tool"

A tool_result block inside the next user message

content blocks and/or structuredContent

Error signal

Error text in the result content, by convention

is_error: true on the result block

isError: true in the result; protocol failures use JSON-RPC errors

The practical move, once you have seen two dialects, is to stop letting either one into your business logic. Define your own internal types — a ToolCall with { id, name, args }, a ToolResult with { id, output, isError } — and write a thin adapter per provider that maps in and out. Your executor, validator, authorizer, and audit log then speak one vocabulary, and switching or adding a model becomes an adapter, not a refactor.

Log the raw payload anyway, before adaptation. When a dialect changes under you — and it will — the adapter is where the breakage lands, and the raw message is the only evidence of what actually arrived.

How tool calling became a protocol question

  • 2023-03-23ChatGPT plugins connect a model to third-party APIs:

    An OpenAPI manifest plus a natural-language description was all it took to hand a model somebody else’s API. Plugins proved the demand for tool integration and exposed the two problems a real protocol has to solve: discovery, and what happens when the tool’s output is hostile.

  • 2023-06-13OpenAI ships function calling:

    Models return structured requests to call functions you declared as JSON Schema. Tool use stops being a prompt-parsing hack and becomes an API contract — the single enabling primitive for production agents, and the reason tool calling belongs to the platform rather than to your prompt.

  • 2024-11-05MCP specification revision 2024-11-05:

    The first protocol revision: the initialize handshake, stdio and HTTP+SSE transports, and the three primitives — tools, resources, prompts. It is now marked Final, and everything later in the MCP story is a revision to this shape.

  • 2024-11-25Anthropic open-sources the Model Context Protocol:

    Spec, SDKs, local server support in Claude Desktop, and a repository of pre-built servers (Google Drive, Slack, GitHub, Git, Postgres, Puppeteer) shipped together, with Block, Apollo, Zed, Replit, Codeium, and Sourcegraph named as early adopters. Write the integration once, and any compliant client can use it — the reason the industry converged on it within a year.

  • 2025-03-26MCP 2025-03-26: OAuth authorization and Streamable HTTP:

    The revision that made MCP deployable over the network: an authorization framework built on OAuth 2.1 (still an IETF draft, not a published RFC), Streamable HTTP replacing HTTP+SSE, plus tool annotations and audio content. HTTP+SSE is deprecated from here — deprecated, not removed.

  • 2025-04-09Google announces the Agent2Agent protocol:

    A2A launched at Cloud Next ’25 as a draft spec for agent-to-agent communication — agent cards for discovery, tasks for delegation — with 50-plus partners endorsing it and an explicit framing as complementary to MCP, not a competitor to it. Treat the partner count as endorsement, not shipped integrations.

  • 2025-06-18MCP 2025-06-18: elicitation, structured output, resource-server model:

    JSON-RPC batching came out; elicitation (the server asking the user for input mid-call), structured tool output, and resource links went in. Security-wise this is the important one: MCP servers are classified as OAuth resource servers (RFC 9728) and must honour Resource Indicators (RFC 8707), which is what stops a token issued for one server being replayed at another.

  • 2025-06-23Google donates A2A to the Linux Foundation:

    The Agent2Agent Protocol project launched at Open Source Summit North America with AWS, Cisco, Microsoft, Salesforce, SAP, and ServiceNow joining — a protocol owned by one cloud is not a standard anyone else builds on. The IBM-originated Agent Communication Protocol later folded into A2A rather than competing with it.

  • 2025-07-30A2A specification v0.3.0:

    The last major pre-1.0 release, widening A2A beyond its original JSON-RPC-and-SSE design toward the gRPC and HTTP+JSON bindings that become normative in v1.0. Anything you built against a 0.x revision needs a version check before you call it interoperable.

  • 2025-07-31MCP publishes a formal governance model:

    “Building to Last” introduced a maintainer hierarchy and a SEP proposal process — the machinery a protocol needs before competitors will commit engineering to it. Governance is why MCP revisions arrive on a schedule instead of by announcement.

  • 2025-09-08The official MCP Registry opens in preview:

    A central metadata repository for public MCP servers — the discovery layer the ecosystem had been faking with README lists. As of September 2026 it is still preview, and the project warns that breaking changes or data resets may occur, so do not build a production dependency on its API shape.

  • 2025-11-25MCP 2025-11-25 lands on the protocol’s first anniversary:

    Icons, URL-mode elicitation, tool calling during sampling, Client ID Metadata Documents, experimental tasks, JSON Schema 2020-12 as the default dialect, and an SDK tiering system. One year, four revisions — treat the revision string in your client as a compatibility fact, not a footnote.

  • 2025-12-09The Agentic AI Foundation forms; Anthropic donates MCP:

    AAIF launched as a directed fund under the Linux Foundation with founding projects MCP, goose, and AGENTS.md, and platinum members including AWS, Anthropic, Block, Bloomberg, Cloudflare, Google, Microsoft, and OpenAI. MCP’s maintainers and governance carried on unchanged — the donation transfers the trademark and neutrality, not the roadmap.

  • 2026-03-12A2A specification v1.0.0:

    The first stable major: three normative bindings (JSON-RPC, gRPC, HTTP+JSON), the proto file as the single source of truth, and A2A-Version header negotiation. v1.0.1 followed on 28 May 2026. Adoption still lags the spec — as of September 2026 Microsoft Foundry’s A2A features are public preview and Google ADK marks A2A support experimental.

  • 2026-07-28MCP 2026-07-28: the protocol goes stateless:

    The current revision removes the initialize handshake and protocol-level sessions, adds server/discover, replaces server-initiated requests with MRTR, and introduces subscriptions/listen. Roots, sampling, logging, and Dynamic Client Registration are deprecated — deprecated, with removal no earlier than 28 July 2027. A release candidate had been published on 21 May 2026.

  • 2026-08-27A2A joins the Agentic AI Foundation:

    A2A was accepted as a Growth Stage project in AAIF, putting it under the same neutral roof as MCP, goose, and AGENTS.md. The two halves of the agent protocol stack now share governance — the announcement claims 150-plus supporting organisations, which is endorsement rather than deployment.

Key terms: function calling, MCP, tool call, tool result, JSON Schema

Interactive checkpoint quiz (2 questions) — open this page in a browser to take it.