Documentation
Concepts

Tracing

Flapjack records span-tree traces for every agent turn and runner run. View execution details, LLM calls, tool invocations, and costs.

Flapjack automatically records a structured trace for every agent turn and runner run. Traces provide full visibility into what happened during execution — LLM calls, tool invocations, MCP requests, conditions, and costs.

Data Model

Trace (log_traces)
  └── Span (log_spans)        — one per semantic operation
        └── Evaluation (log_evaluations)  — async quality scores
  • Trace: Root record, one per agent message or runner run
  • Span: A single operation within a trace (LLM call, tool execution, etc.)
  • Evaluation: Optional quality scores attached to spans (heuristic, LLM-judge, or human)

Span Kinds

KindDescription
agentTop-level agent execution
runner_stepA single step in a runner pipeline
llmLLM inference call
toolTool execution (webhook, custom, etc.)
mcpMCP server tool call
webhookWebhook invocation
conditionCondition evaluation in runner flows
embeddingEmbedding/RAG lookup
guardrailGuardrail check
chainMulti-step chain

Span Fields

Each span includes:

FieldDescription
idSpan UUID
trace_idParent trace UUID
parent_span_idParent span (null for root spans)
kindSpan kind (see above)
nameHuman-readable label
statusrunning, ok, or error
started_at / ended_atTimestamps
input / outputJSONB payloads (truncated to ~256 KB)
errorError details if status is error

LLM spans additionally include: provider, model, temperature, max_tokens, input_tokens, output_tokens, cached_input_tokens, cost_usd.

Viewing Traces

List Traces

GET /api/logs
ParameterTypeDescription
limitnumberMax results (default 50, max 200)
cursorstringComposite cursor (<startedAt>|<traceId>) for pagination
agent_idstringFilter by agent
runner_idstringFilter by runner
thread_idstringFilter by thread
run_idstringFilter by runner run
statusstringFilter by status
qstringSubstring search on trace name

Response:

{
  "traces": [
    {
      "id": "trace-123",
      "name": "Agent turn",
      "status": "ok",
      "started_at": "2026-05-10T12:00:00Z",
      "ended_at": "2026-05-10T12:00:03Z",
      "span_count": 5,
      "error_count": 0,
      "llm_call_count": 2,
      "tool_call_count": 1
    }
  ],
  "nextCursor": "2026-05-10T11:59:00Z|trace-122"
}

Get Trace Detail

GET /api/logs/{traceId}

Returns the full trace with all spans (sorted by execution order) and evaluations:

{
  "trace": { "id": "trace-123", "name": "Agent turn", "status": "ok", "..." : "..." },
  "spans": [
    { "id": "span-1", "kind": "agent", "name": "Support Agent", "status": "ok", "..." : "..." },
    { "id": "span-2", "kind": "llm", "name": "claude-sonnet-4-6", "model": "claude-sonnet-4-6", "input_tokens": 1200, "output_tokens": 350, "cost_usd": 0.0084, "..." : "..." },
    { "id": "span-3", "kind": "mcp", "name": "github:list_issues", "status": "ok", "..." : "..." }
  ],
  "evaluations": []
}

Cost Attribution

Every LLM span records cost_usd, input_tokens, output_tokens, and cached_input_tokens. These roll up into the analytics endpoints for per-agent and per-runner cost tracking.

Next Steps

Docs last updated May 11, 2026