Skip to content

Events and run context

Standard event helpers

AgentLogger provides helpers for common workflow boundaries:

Helper Important arguments
user_message message
system_instruction instruction
model_call provider, model, token counts, payload
model_response provider, model, payload
tool_call tool_name, args
tool_result tool_name, result
retrieval_query query, source
retrieval_result source, result
policy_check policy_name, status, payload
human_approval approver, status, payload
decision decision, requires_human_review
error an exception or string

Each helper returns the written AgentEvent, which is useful for correlation.

Tool decorator

Use trace_tool around ordinary synchronous Python functions:

@log.trace_tool("snowflake.query")
def run_query(sql: str):
    return {"rows": 20}

The decorator emits tool_call before invoking the function and a correlated tool_result after success. Exceptions emit a correlated error and are re-raised. Arguments and results follow the logger's redaction policy. functools.wraps preserves the wrapped function's name, docstring, and introspection metadata.

Model-call context

Use trace_model_call when an SDK call does not need a dedicated wrapper:

with log.trace_model_call("azure_openai", "gpt-4.1") as trace:
    response = client.responses.create(...)
    trace.set_response({"response_id": response.id})

Entering emits model_call. set_response schedules a correlated model_response on successful exit. It is optional; a context without it records only the call boundary. Exceptions emit error and are re-raised. These helpers are synchronous; async-native logger contexts remain a roadmap item.

Run lifecycle

AgentLogger.run() creates a UUID4 run ID and stores it in a context variable. Nested functions do not need the run ID passed explicitly:

def call_tool(log):
    log.tool_call("inventory.lookup", {"sku": "A-123"})

with log.run():
    call_tool(log)

Nested run contexts restore the outer run ID when the inner context exits.

Direct emission

Use emit when a standard helper does not fit:

log.emit(
    "custom",
    {"name": "cache_hit", "key_namespace": "pricing"},
    status="success",
)

Arbitrary event type names are rejected by default. For interoperability, prefer the custom type with a descriptive payload. Low-level consumers can explicitly construct AgentEvent(..., allow_custom_event_types=True) when a distinct name is required.

Parent relationships

Use parent_event_id to connect a result to the event that initiated it:

call = log.tool_call("search", {"query": "margin"})
log.tool_result("search", {"matches": 4}, parent_event_id=call.event_id)