Agent identity
Every trace routes by agent name. How identity is set on each integration path, how to run more than one agent, and what failure looks like when a name is missing.
Every trace that reaches AISquare carries an agent name. The gateway routes each trace by the pair (workspace, agent name) to a studio and its Rule Book, and the dashboard groups runs, verdicts, and cost by the same name. A trace without a name has nowhere to go. This page is the contract: where the name lives, how each integration path sets it, and what breaks when it is missing.
Why identity exists
Identity is written to the trace as attributes["agent.name"] on the trace's
root span. The gateway reads it once per trace and uses it three ways:
- Routing. Each trace routes by (workspace, agent name) to a studio. This is how a run ends up on the right dashboard.
- Rule Book binding. The name decides which Rule Book judges the run. Bind
a Rule Book to
support-botand every run namedsupport-botis evaluated against it. - Grouping. Runs, policy verdicts, and cost aggregate per agent. The name is the axis.
Two channels, one name
The SDK carries identity on two channels. They answer different questions, and you should keep them equal.
- Span identity (
agent.nameon the root span) routes the trace and groups your dashboards. - Policy identity (
AISQUARE_AGENT_NAME) tells policy checks which Rule Book judges the agent.
From SDK 1.0.6 the two are unified: AISQUARE_AGENT_NAME also serves as the
fallback trace identity. When a span batch arrives with no explicit name
on its root span, the SDK stamps it with AISQUARE_AGENT_NAME. Explicit
naming in code always wins; the env var is the safety net. Keep it equal to
your agent_name so both channels agree.
How identity is set, per path
Explicit naming is the contract. Each integration path has exactly one place to put the name.
| Path | Where the name goes |
|---|---|
| Raw pipeline / custom spans | AgentRunTracer(agent_name=...) |
| Agno | Agent(name=...) — required |
| LangChain | metadata={"agent_name": ...} in the invoke config |
Custom or OpenAI-wrapped via GovernedAgent | agent_name= on the wrapper; tracing is automatic (SDK 1.0.6) |
| Proxy | X-Agent-Name header |
Raw pipelines. Open an AgentRunTracer around the run. Its agent_name
lands on the root span and every child inherits the route.
# .env: EXPLAINABILITY_GATEWAY_URL, EXPLAINABILITY_API_KEY,
# EXPLAINABILITY_AGENTS=support-bot <- pre-registers; must equal agent_name below
import aisquare.explainability as sdk
sdk.init_from_env()
with sdk.AgentRunTracer(agent_name="support-bot"):
with sdk.LLMCallTracer(model="gpt-4o", provider="openai") as llm:
...
sdk.flush()Agno. The agent must be named. The SDK reads Agent(name=...) and uses it
as the trace identity; an unnamed Agno agent has no identity to send.
my_agent = Agent(name="support-bot", ...)LangChain. Pass the name in the invoke config's metadata. The callback handler picks it up per call.
chain.invoke(inputs, config={"metadata": {"agent_name": "support-bot"}})Custom and OpenAI-wrapped agents. From SDK 1.0.6, GovernedAgent
auto-opens an AgentRunTracer around .run() and .arun(), so the wrapped
agent is traced and named in one move.
agent = GovernedAgent.wrap(my_agent, agent_name="support-bot")
agent.run("...") # traced automatically, routed as support-botProxy. Identity comes from the X-Agent-Name header on each request. If
the header is absent, the proxy falls back to the pipeline id
(X-Pipeline-Id), then to claude-code. Set the header if you want the name
to mean something.
Running more than one agent
Name each agent in code. AISQUARE_AGENT_NAME holds one name; it is a
single-agent convenience, not a naming scheme.
Pre-register your roster
EXPLAINABILITY_AGENTS takes a comma-separated list of agent names and
registers them at init_from_env(), so the first trace from each agent routes
immediately instead of waiting on registration.
export EXPLAINABILITY_AGENTS="support-bot,billing-bot"The names must equal the agent_name values used in code, character for
character. A roster entry that matches nothing registers an agent that never
runs; a coded name missing from the roster still needs registration before its
first trace routes.
Naming rules
- Unique per workspace. The name is the routing key; two agents sharing a name are one agent as far as AISquare is concerned.
- Stable across deploys. Rule Book bindings key off the name. Rename the agent and its bindings, history, and dashboards do not follow.
- Allowed characters: letters, digits,
.,_,-, and spaces.
What failure looks like
When identity is missing or unknown, trace ingest answers 409 Conflict with
a machine-readable code in detail.code:
| Code | Meaning | What to do |
|---|---|---|
no_agent_identity | A root span arrived with no identity on it. | Fix the integration — name the agent. Retrying will not succeed. |
awaiting_trace_route | A child-only batch arrived before its root span. | Transient. The SDK retries it automatically. |
agent_not_registered | The name is set but not registered in the workspace. | Register the agent, or enable auto-discovery on the workspace. |
Full remediation for each code is in the
error reference. If you
are not sure which case you are in, run explainability-doctor: its
agent_identity check flags naming gaps in your integration, and its
delivery_backlog check reads the local delivery queue and reports exactly
which of these failures is holding traces back.
Next steps
Connect your agents
Two ways to send your agents to AISquare, the SDK and the multi-provider proxy. Both give full observability, governance, and runtime enforcement. They differ on where the gate runs.
Proxy integration
Put your AI agents behind the AISquare proxy. A drop-in gateway that records every run and enforces your Rule Book, for Claude, OpenAI, Azure OpenAI, and Gemini, plus the Claude Code and Codex CLIs.