Primary integration point. Works as a context manager, an async context manager, or a decorator.
def event(
*,
event_id: str | Callable,
customer_id: str | Callable,
workflow: str,
environment: str | None = None,
tenant_id: str | None = None,
auto_outcome_on_success: bool = True,
capture_input: bool | None = None,
span_kind: SpanKind = SpanKind.SERVER,
) -> _Event| Parameter | Description |
|---|---|
event_id |
Business event identifier — the join key for outcome correlation. String, or a callable taking the decorated function's args. In context-manager form must be a resolved string. |
customer_id |
Customer being served. String or callable with the same rules as event_id. |
workflow |
Workflow name (low cardinality). Required. |
environment |
Deployment environment override. Falls back to BOTANU_ENVIRONMENT or OTEL_DEPLOYMENT_ENVIRONMENT. |
tenant_id |
Tenant identifier for multi-tenant apps. |
auto_outcome_on_success |
Mark the run SUCCESS on clean exit. Default True. |
capture_input |
Force content capture on/off. None (default) uses the sampled content_capture_rate. |
span_kind |
OTel span kind. Default SERVER. |
import botanu
with botanu.event(event_id=ticket.id, customer_id=user.id, workflow="Support"):
agent.run(ticket)async with botanu.event(event_id=ticket.id, customer_id=user.id, workflow="Support"):
await agent.arun(ticket)Supports callables for event_id and customer_id:
@botanu.event(
workflow="Support",
event_id=lambda ticket: ticket.id,
customer_id=lambda ticket: ticket.user_id,
)
def handle_ticket(ticket):
...Works for both sync and async def functions.
Context manager for multi-phase workflows. Nests inside an event scope and emits a span with kind=INTERNAL.
with botanu.event(event_id=ticket.id, customer_id=user.id, workflow="Support"):
with botanu.step("retrieval"):
docs = vector_db.query(ticket.query)
with botanu.step("generation"):
response = llm.complete(docs)Each step stamps botanu.step=<name> on its span and propagates it via baggage.