Module: ActiveAgent::Telemetry::ToolOrigin
- Defined in:
- lib/active_agent/telemetry/tool_origin.rb
Overview
Classifies where a tool call came from, so dashboards can group tool traffic by the service that serves it instead of showing a flat list of names.
Telemetry only ever sees the name a provider used to invoke the tool,
so the origin has to be recovered from naming conventions. The MCP
ecosystem settled on a namespaced form — mcp__<server>__<tool> —
which most clients (Claude Code, Cursor, the Ruby MCP clients) emit
verbatim, and that is the strongest signal available. Everything else
falls back to "the agent class defines this method".
Classification happens at instrumentation time rather than at read time so the attribution is recorded in the span itself: a trace stays self-describing, and consumers (the gem dashboard, activeagents.ai, any OTLP exporter) all read the same fields instead of each re-implementing the guess.
Constant Summary collapse
- MCP_PATTERN =
mcp__<server>__<tool>. The tool half may itself contain "__", so only the first two segments are structural. /\Amcp__([^_]+(?:_[^_]+)*?)__(.+)\z/- MCP =
Origin values written to
tool.origin. "mcp"- AGENT =
"agent"
Class Method Summary collapse
-
.annotate(span, name) ⇒ Hash
Writes the classification onto a span.
-
.classify(name) ⇒ Hash
Classifies a tool name.
-
.mcp?(name) ⇒ Boolean
Whether a tool name is namespaced to an MCP server.
-
.server_for(name) ⇒ String?
The MCP server a tool belongs to, if any.
Class Method Details
.annotate(span, name) ⇒ Hash
Writes the classification onto a span. Only sets tool.mcp_server
when there is a server to name, so agent-defined tools don't carry
an empty attribute.
79 80 81 82 83 84 85 86 87 |
# File 'lib/active_agent/telemetry/tool_origin.rb', line 79 def annotate(span, name) classification = classify(name) span.set_attribute("tool.origin", classification[:origin]) if classification[:server] span.set_attribute("tool.mcp_server", classification[:server]) span.set_attribute("tool.base_name", classification[:tool]) end classification end |
.classify(name) ⇒ Hash
Classifies a tool name.
46 47 48 49 50 51 52 53 54 |
# File 'lib/active_agent/telemetry/tool_origin.rb', line 46 def classify(name) name = name.to_s if (match = MCP_PATTERN.match(name)) { origin: MCP, server: match[1], tool: match[2] } else { origin: AGENT, server: nil, tool: name } end end |
.mcp?(name) ⇒ Boolean
Whether a tool name is namespaced to an MCP server.
60 61 62 |
# File 'lib/active_agent/telemetry/tool_origin.rb', line 60 def mcp?(name) MCP_PATTERN.match?(name.to_s) end |
.server_for(name) ⇒ String?
The MCP server a tool belongs to, if any.
68 69 70 |
# File 'lib/active_agent/telemetry/tool_origin.rb', line 68 def server_for(name) classify(name)[:server] end |