Skip to main content
All four SDKs share one wire format, so sessions land in the same dashboard whether your server is TypeScript, Python, Go, or PHP.

Telemetry fields

The SDK adds one optional telemetry object to each instrumented tool’s input schema, with three well-described fields. The calling agent fills them in as it works; the SDK strips the object out before your handler runs, so your business logic never sees it: Agents are told to send agent_thinking on every call, and user_intent and user_frustration on the first call after each new user message — their absence on later calls means the same turn continues, which is how the conversation view knows where turns begin. All fields are optional — agents that ignore them still produce complete sessions with tool calls, timing, and outcomes. Older field spellings (intent, context, frustration_level) are accepted and normalized, and user_turn values from cached schemas are ignored, so agents with stale schemas keep working.
This is why instrumented sessions show what the user asked and what the agent was thinking — not just a list of tool calls. The description hint the SDK appends to each tool tells agents how to fill the fields.

Events

The SDK emits two event kinds: session_init — once per session: client name and version (Claude, ChatGPT, Cursor, …), protocol version, and capabilities. tool_call — one per tool invocation:
  • Tool name, start/finish timestamps, duration
  • Outcome (ok or the error), including MCP results returned with isError: true
  • Telemetry fields reported by the agent
  • A truncated input preview and result preview

The request_capability tool

With analytics enabled, the SDK also registers one small tool of its own: request_capability. Its description tells agents to call it when the user needs something no existing tool can do; each call is recorded like any other and feeds unmet demand. A tool of the same name that you define yourself takes precedence, and the injection is skipped when analytics is disabled or no delivery is configured. Set requestCapability: false (request_capability in Python, RequestCapability in Go) to opt out.

Size limits

Payloads are truncated UTF-8-safely before they leave your process:

Sessions and actors

  • Session identity comes from the MCP session: HTTP servers use the Mcp-Session-Id header; stdio servers get a process-scoped session ID, so each CLI conversation is its own session. Stateless HTTP servers need one extra helper.
  • Actor identity is a SHA-256 hash of a seed derived from the request’s auth (token, client ID, or Authorization header), falling back to anonymous. Raw seeds never leave your server; the opt-in actorIdentifier is the deliberate exception — see Identifying users.

Delivery guarantees

  • Events post to Armature’s ingest API over HTTPS, authenticated with your ingest key.
  • Delivery runs off the request path by default in the TypeScript, Python, and Go SDKs (background mode). The PHP SDK awaits delivery by default, because PHP is request-scoped. In every SDK, delivery never throws into your tools — failures go to your onError hook.
  • If no ingest key is configured, the SDK no-ops: schemas are still decorated, but nothing is sent.
The agent-facing schema hint instructs agents not to put secrets or PII in telemetry fields, and Armature scans and redacts incoming sessions before storage.