Identifying users
identify_user associates a stable user ID — and optional traits — with the current run. Traits are free-form: a plan, a company, a cohort.
client.identify_user("cus_123", traits={"plan": "pro", "company": "Acme"})Scoped user context
When you handle many runs for the same user, the user(...) context manager scopes identity to a block — every trace opened inside it inherits the user automatically.
with client.user(user_id="cus_123", traits={"plan": "pro"}): with client.trace("agent_run") as trace: ... # this trace is attributed to cus_123Feedback vs signals
Both record an outcome on a trace, but they mean different things:
feedback— explicit reactions from the user: a thumbs-up, a star rating, a CSAT score.signal— implicit behavioral or business outcomes the user didn't explicitly give: an order was placed, a ticket was reopened, a session converted.
Both can be called on the trace, the client, or the module:
trace.feedback("thumbs_up", True)trace.signal("order_placed", {"order_id": "ord_123"})Attaching to a known trace
Feedback and signals often arrive after the run has finished — a rating submitted minutes later. When you only have the trace ID, pass it explicitly and the event attaches to the right trace.
client.feedback("csat", 5, trace_id="trace_abc")client.signal("ticket_reopened", True, trace_id="trace_abc")Tip
Keep the trace_id from a run (or set your own external_trace_id on the trace) so you can correlate late-arriving outcomes back to the run that produced them.