Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.flowx.ai/llms.txt

Use this file to discover all available pages before exploring further.

Everything Observatory shows is built on top of a stream of events. The decorators emit them for you, but you can also call track_event() directly when you need a custom signal.

The wire protocol

Events are HTTP-POSTed to /api/report as a JSON object with an events array. Each event is one object:
{
  "name": "agent_start",
  "app_id": "...",
  "run_id": "...",
  "parent_run_id": null,
  "timestamp": "2026-05-29T08:42:11.123Z",
  "type": "agent",
  "metadata": {"user_email": "..."},
  "input": { ... },
  "output": null
}
The API authenticates each request with Authorization: Bearer <FLOWX_OBSERVATORY_API_KEY> and resolves app_id from the metadata or, failing that, from the project the key belongs to.

Batching

The SDK queues events in memory and a background consumer flushes them on a short interval, posting each batch as {"events": [...]} to /api/report. On shutdown, the SDK flushes the remaining queue. Delivery is best-effort — if a flush fails, those events are dropped rather than blocking your app.

Cost and token rules

The Observatory API computes cost only for events with type=llm. The rules:
  1. The event must include prompt_tokens and completion_tokens (or total_tokens).
  2. The event must include model.
  3. There must be a row for the model in the API’s model cost table.
Missing any of these → cost = 0 for that event.
Adding a new model to your stack requires adding a cost row. Until that happens, the model’s calls show up in traces but accumulate zero cost. Run the cost recalc job after editing the table.

Custom events

Three custom events have semantic meaning to Observatory:

saved

Marking a run as saved persists it past retention windows and surfaces it for dataset workflows.
from flowxobservatory import track_event

track_event("saved", run_id=ctx.run_id)
Use after a human has signed off on the run — e.g. a reviewer approving a generated document.

chat

A chat event represents one message in a conversation. The Threads view groups consecutive chat events by thread_id into a single thread.
track_event(
    "chat",
    role="user" or "assistant",
    content="...",
    thread_id="cust-42",
)
Without thread_id, the SDK falls back to grouping by agent + user within a 30-minute window.

feedback

Attaching feedback to a run or thread message.
track_event(
    "feedback",
    run_id=ctx.run_id,
    rating="positive" or "negative",
    comment="...",
)
Feedback shows up alongside the run in LLM Calls, on the message in Threads, and contributes to the Manage 4.2 NIST control.

Advanced filtering

The runs endpoint accepts the full filter set used by the LLM Calls UI:
GET /api/run/?app_id=...&status=error&model=gpt-4&min_latency_s=8&tags=high-risk
Supported filters:
ParameterTypeNotes
statusenumsuccess / error / started.
modelstringExact match.
agentstringExact match.
min_latency_s / max_latency_sfloatWall-clock seconds.
min_cost / max_costfloatUSD.
tagslistAny-of match.
user_emailstringExact match.
from / toISO timestampInclusive window.

Direct API use

If you can’t use the Python SDK (different language, edge environment), report events directly:
curl -X POST "$FLOWX_OBSERVATORY_API_URL/api/report" \
  -H "Authorization: Bearer $FLOWX_OBSERVATORY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"events": [{
    "name": "agent_start",
    "type": "agent",
    "run_id": "01HXYZ...",
    "timestamp": "2026-05-29T08:42:11.123Z",
    "input": {"prompt": "..."},
    "metadata": {"agent": "claims-approval"}
  }]}'
The shape mirrors the Python SDK’s payload exactly.

Decorators

The Python wrappers that emit standard events for you.

Threads

Where chat events become conversations.
Last modified on June 2, 2026