Contract
Plugins register observer callbacks fromregister(ctx):
**kwargs so additive fields remain backward-compatible:
Telemetry plugins should treat these behavior-affecting returns as optional
compatibility features, not as observability requirements.
Correlation IDs
Observer payloads use stable IDs so plugins can join events without relying on callback order alone.
Consumers should prefer explicit fields over parsing compound IDs. In
particular,
api_request_id is an opaque correlation value.
Event Families
Session Lifecycle
Session hooks describe conversation boundaries and resets:
Common fields include
session_id, completed, interrupted, reason,
old_session_id, and new_session_id where available.
on_session_end is turn/run scoped. It is not necessarily the final lifetime
boundary for a chat identity. Use on_session_finalize and on_session_reset
for lifecycle cleanup that must happen once per session identity.
Turn-Scoped LLM Hooks
These hooks frame the user turn, not individual provider API attempts:
Common
pre_llm_call fields include session_id, turn_id,
user_message, conversation_history, is_first_turn, model, platform,
and sender_id.
Common post_llm_call fields include session_id, turn_id,
user_message, assistant_response, conversation_history, model, and
platform.
Use request-scoped API hooks for LLM span telemetry. Use pre_llm_call and
post_llm_call for turn-level context, compatibility, and final turn summary.
Request-Scoped API Hooks
API hooks describe provider attempts inside the agent loop:pre_api_request includes:
- identity:
session_id,task_id,turn_id,api_request_id - runtime:
platform,model,provider,base_url,api_mode - attempt metadata:
api_call_count,message_count,tool_count,approx_input_tokens,request_char_count,max_tokens - timing:
started_at - sanitized request payload:
request
post_api_request includes the same identity/runtime fields plus:
api_duration,started_at,ended_atfinish_reason,message_count,response_modelusageassistant_content_chars,assistant_tool_call_count- sanitized response payload:
response - compatibility object:
assistant_message
api_request_error includes the same identity/runtime fields plus:
api_duration,started_at,ended_atstatus_code,retry_count,max_retries,retryable,reason- structured
error = {"type": ..., "message": ...} - sanitized failed request payload:
request
request, response, and error fields are the canonical
observer inputs for new consumers.
Tool Lifecycle
Tool hooks describe individual tool calls:pre_tool_call includes tool_name, args, task_id, session_id,
tool_call_id, turn_id, and api_request_id.
post_tool_call includes the same identity fields plus result,
duration_ms, status, error_type, and error_message.
status is the observer-grade lifecycle outcome. Common values include:
post_tool_call is emitted for blocked and cancelled paths so telemetry
plugins can close spans cleanly.
Approval Lifecycle
Approval hooks describe dangerous-command approval prompts:
Common fields include
command, description, pattern_key,
pattern_keys, session_key, and surface.
post_approval_response also includes choice, with values such as once,
session, always, deny, timeout, and cancelled (nobody answered: the prompt
was withdrawn — turn interrupted or ended — or never reached the user on the CLI).
Approval hooks are observer-only. Plugins cannot pre-answer or veto approvals
from these hooks. To prevent a tool from reaching approval, use
pre_tool_call blocking.
Subagent Lifecycle
Subagent hooks describe delegated child-agent work:subagent_start fields include parent_session_id, parent_turn_id,
parent_subagent_id, child_session_id, child_subagent_id, child_role,
and child_goal.
subagent_stop fields include parent/child session IDs, role/status fields,
child_summary, duration_ms, and a metadata-only tool_call_history. Each
history entry contains the tool name, argument names, bounded side-effect
targets, input/output byte counts, and outcome. URL query strings and fragments
are removed; raw arguments, prompts, commands, contents, headers, and results
are intentionally excluded.
Observers can use these hooks to model nested trajectories while keeping child
agent execution linked to the parent turn that spawned it.
Payload Safety
Observer payloads are designed for telemetry consumers, not raw object access. New consumers should use the sanitized API payloads:pre_api_request.requestpost_api_request.responseapi_request_error.requestapi_request_error.error
request_messages, conversation_history,
and assistant_message may still be present for existing plugins. New
observability consumers should prefer the sanitized payloads.
Performance
The default uninstrumented path should stay cheap. Expensive request/response payload construction is gated behindhas_hook(...), so Mibyan only builds
sanitized API telemetry payloads when at least one plugin registered the
relevant hook.
Plugin authors should preserve this property:
- Register only hooks the plugin actually consumes.
- Avoid deep-copying or re-sanitizing already sanitized payloads.
- Keep hook callbacks fast and fail-open.
- Offload network export or batch writes when practical.
Writing An Observer Plugin
Minimal observer plugin:session_id, turn_id, api_request_id, and tool_call_id for span
correlation. Use subagent and approval hooks when the export format supports
nested agent work or security lifecycle events.
Existing Consumers
The bundled Langfuse plugin demonstrates direct hook-based observability for turns, provider requests, and tool calls. The native NeMo Relay SDK integration maps Mibyan session, turn, LLM, and tool lifecycles to Relay. Relay’s discovered user and system configuration, or an explicit file selected withmibyan_NEMO_RELAY_PLUGINS_TOML, can add
ATOF, ATIF, or OTEL
exporters and execution middleware; see
Relay shared metrics.
