foundry · flux github.com/zaakirio/flux ↗

flux

One trace across the whole fleet.

Real agent systems are not one framework. A request starts in a TypeScript agent, crosses into a Python agent, and the story fragments: every framework has its own idea of a trace and its own cost accounting. flux ingests OpenTelemetry spans over OTLP/HTTP, stitches them into one distributed trace with W3C Trace Context, discovers agents from their A2A Agent Cards, and binds USD cost to each task. The only contracts are open standards, so any agent that speaks them shows up.

flux banner: a single trace spine crossing agent nodes, in the flux violet

How it works

The make-or-break capability, proven end to end with real telemetry: one request from the quench triage agent (TypeScript, AI SDK) crosses into the anvil docs agent (Python, LangGraph), and flux shows it as one trace with per-agent cost.

  1. 01
    Emit.

    Both agents run the genuine OpenTelemetry SDK (JS and Python) and export OTLP/HTTP JSON to flux's ingest route, POST /v1/traces. Spans have real ids, timing, parent links, and resource attributes.

  2. 02
    Propagate.

    quench injects its active span's W3C traceparent into the outgoing A2A request; anvil extracts it, so the Python spans become children of the TypeScript span that called them. The proof asserts exactly this parent link.

  3. 03
    Stitch and store.

    flux parses resourceSpans, reads service.name from each resource, and stores every span with its parent link and attributes in an embedded SQLite store.

  4. 04
    Discover.

    Each agent serves a spec-1.0 A2A Agent Card at /.well-known/agent-card.json; flux fetches and stores them so the fleet roster shows real identities and skills, not config strings.

  5. 05
    Bind cost.

    USD is computed from the gen_ai token-usage attributes carried on the spans against a dated July 2026 price table, to sub-cent precision, attributed to agent and task.

traces / quench.triage · 8ed6c8f4 · the stitched timeline, span by span
quench.triage                          quench   20.80s
├─ triage.classify                     quench   10.8ms   $0.0006
├─ triage.consult_docs  a2a -> anvil   quench   20.78s
│  └─ anvil.answer_grounded_question   anvil    20.76s   ← cross-service hop
│     ├─ retrieve       25 candidates  anvil    12.23s
│     ├─ rerank         kept 8         anvil     8.46s
│     └─ answer         1757 in/75 out anvil             $0.0064
├─ triage.investigate   17440 in/1030  quench            $0.0678
└─ triage.diagnose                     quench    0.1ms
                                                task total  $0.0748

The panes

The landing page is the Fleet Overview: what the fleet is doing, what it costs, and whether it is healthy, aggregated live from every span in the store. It is honest about fleet size: two agents plus one MCP tool node, and nothing invented to fill the dashboard.

flux Fleet Overview: header stats showing $0.0748 fleet cost, 1 task, 9 spans, 20,762 tokens; roster cards for quench, anvil, and bellows with eval badges; cost-by-agent and cost-by-task bar charts
Fleet Overview: live aggregates from the span store, per-agent roster with real eval headlines, cost analytics as inline SVG.
flux stitched timeline for the quench.triage trace: nine spans across two services, the anvil spans indented under the quench span that called them, with per-span duration and cost
The stitched timeline: one request crossing quench (TS) into anvil (Python), the cross-service hop flagged, cost on every model span.

Quickstart

Requirements: Node 22+, Python 3.13+ with uv, and Docker for the Postgres that anvil retrieves from. The demo is offline and keyless but the telemetry is real.

flux · zsh
# unit tests: OTLP parse, parent-child stitch, cost math, card fetch
npm install
npm run test

# the make-or-break: a real TS->Python trace, stitched, asserted
npm run proof

# end-to-end demo: starts flux + anvil + quench, runs one real triage
# across the boundary, confirms the stitched trace
./scripts/demo.sh
# open http://127.0.0.1:3100

Limitations, stated plainly

  • The OpenTelemetry GenAI semantic conventions are still experimental; the gen_ai.* attribute names used here are current as of mid-2026 but may shift.
  • A2A tracing is opt-in: agents only join a trace if they are instrumented and honor incoming traceparent. flux does not magically trace an uninstrumented agent.
  • Single-machine slice: the store is embedded SQLite and ingest is one process. This is a de-risking slice, not a horizontally scaled collector.
  • flux ingests OTLP/HTTP JSON specifically, not protobuf.
  • Offline, the agents drive real tool loops with a deterministic stand-in model, so absolute cost figures illustrate the mechanism (binding real token attributes to a dated price table) rather than live model spend. Set an API key and the same spans carry real token usage.

Copied from the Limitations section of the flux README, 2026-07-08. If a number on this page and the repo ever disagree, the repo wins.