Agents
Multi-agent observability and analytics.
Track individual agent performance and inter-agent interactions.
Agent Identity
Define agent identity in your code:
from risicare import agent
@agent(name="researcher", role="specialist")
def research_agent(query: str):
# Agent code here
passOr with context managers:
from risicare import agent_context
with agent_context(
"planner-001", # agent_id (required, positional)
agent_name="planner",
agent_role="orchestrator",
agent_type="custom",
version=1,
):
# Agent code here
passAgent Attributes
| Attribute | Type | Description |
|---|---|---|
agent_id | string | Unique instance ID (required, first positional argument) |
agent_name | string | Human-readable agent name (falls back to agent_id) |
agent_role | string | orchestrator, worker, specialist, etc. |
parent_agent_id | string | Parent in hierarchy (set automatically when nesting) |
agent_type | string | Framework-specific type (langgraph, crewai, autogen, custom) |
version | int | Agent version number |
metadata | dict | Custom agent metadata |
Agent Roles
| Role | Description |
|---|---|
orchestrator | Coordinates other agents |
worker | Executes assigned tasks |
supervisor | Monitors and validates |
specialist | Domain expert |
router | Routes messages/tasks |
aggregator | Aggregates results |
broadcaster | Broadcasts to multiple agents |
critic | Reviews and critiques |
planner | Creates execution plans |
executor | Executes plans |
retriever | Retrieves information |
validator | Validates outputs |
JS SDK has a different role set
The JavaScript SDK's AgentRole enum has 14 values — the 12 shared with Python plus reviewer and custom. See the JS SDK reference for the full list.
Agent Dashboard

The KPI strip shows: Total Agents, Invocations (with trace count), Success Rate (with errors), Avg Latency (with P95), Total Errors (with error rate), and Total Cost (with tokens).
Agent List
View all agents with metrics:
| Column | Description |
|---|---|
| Name | Agent name |
| Role | Agent role |
| Invocations | Total calls |
| Avg Latency | Average response time |
| Error Rate | Failure percentage |
| Avg Tokens | Average token usage |
| Avg Cost | Average cost per call |
Agent Detail
Deep dive into a single agent:

- Performance: Latency percentiles, throughput
- Tokens: Usage by model
- Errors: Top error codes, failure patterns
- Interactions: Agents it calls and is called by
Some agent metrics are not yet populated (in flight)
The agent metrics derived from span/trace data are live today: invocations, success/error rate (from has_error), latency percentiles, token usage, cost, the agent hierarchy, the interaction graph, and semantic_phase (captured end-to-end). A second set of agent-semantic fields — per-tool success/failure counts (tool_success), iteration / max_iterations, delegation depth, and per-phase time splits (think/decide/act_time) — have dashboard columns and read-API fields wired, but the SDK does not yet emit the source attributes, so they currently read empty or 0. Populating them is part of in-progress agent-semantics work. Until then, rely on the span-derived metrics above.
Agent Hierarchy
Track parent-child relationships:
@agent(name="orchestrator", role="orchestrator")
def orchestrator():
with agent_context(
"researcher-001",
agent_name="researcher",
agent_role="specialist",
):
research()
with agent_context(
"writer-001",
agent_name="writer",
agent_role="specialist",
):
write()Visualized as:
orchestrator (orchestrator)
├── researcher (specialist)
└── writer (specialist)
Inter-Agent Communication
Track messages between agents:
from risicare import trace_message
@trace_message(target="researcher-001", target_name="Researcher")
def send_research_request(task: str):
return researcher.process(task)Message Types
What the SDK actually emits today
The SDK decorators (trace_message, trace_delegate, trace_coordinate) only emit three message types: message, delegation, and coordination. The broader MessageType enum below is reserved for manual/aspirational use — those values are not produced automatically by the SDK and must be set by hand on the span if you need them.
| Type | Description |
|---|---|
task | Task assignment |
result | Task result |
status | Status update |
error | Error notification |
query | Information request |
response | Information response |
broadcast | Broadcast to all |
direct | Direct message |
proposal | Propose action |
vote | Vote on proposal |
consensus | Consensus reached |
conflict | Conflict detected |
heartbeat | Agent alive signal |
shutdown | Shutdown signal |
handoff | Handoff to another agent |
JS SDK has a different message type set
The JavaScript SDK's MessageType enum has 18 values (e.g. REQUEST, RESPONSE, DELEGATE, COORDINATE, BROADCAST, VOTE, HANDOFF, …). See the JS SDK reference for the full list.
Message Attributes
| Attribute | Description |
|---|---|
sender | Sending agent name |
receiver | Receiving agent name |
message_type | One of the types above |
content | Message content |
correlation_id | Links request/response |
Agent Delegation
Track when agents delegate tasks:
from risicare import trace_delegate
@trace_delegate(target="executor-001", target_name="Executor")
def delegate_execution(plan: dict):
return executor.execute(plan)Agent Analytics
Performance Comparison
Compare agents across:
- Latency (P50, P95, P99)
- Error rate
- Token efficiency
- Cost per operation
Interaction Graph
Visual network showing:
- Agent nodes
- Communication edges
- Message volume
- Error paths
Bottleneck Analysis
Identify slow agents:
- Agents on critical path
- High-latency operations
- Token-heavy agents
- Error-prone agents
Agent Iterations
Record iteration counts on iterative agent loops via agent metadata. (Note: this stores the value in the span's metadata; the dedicated iteration / max_iterations agent analytics are not yet auto-populated — see the in-flight note above.)
@agent(name="refiner", role="specialist")
def iterative_refine(content: str, max_iterations: int = 3):
for i in range(max_iterations):
with agent_context(
"refiner-001",
agent_name="refiner",
metadata={"iteration": i + 1}
):
content = refine_step(content)
if is_good_enough(content):
break
return contentFiltering Agents
# By name
name:researcher
# By role
role:orchestrator
# By performance
latency_p99:>5000
error_rate:>0.1
# By activity
invocations:>1000