Pick a backend (or run both side by side - they coexist on different ports). All paths work identically through core's tracing.bootstrap().
uv sync --all-packages
make phoenix-up # docker compose, always-on (or `make phoenix-fg` for foreground)
make phoenix-bootstrap # one-time annotation configs + datasets
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:6006 make luca-demo
python -m webbrowser http://localhost:6006 # Phoenix Sessions tabuv sync --all-packages
make tempo-up # docker compose Tempo + Grafana
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318 make luca-demo
python -m webbrowser http://localhost:3000/d/luca-flow/luca-flowtracing.bootstrap() ships standard OTLP/HTTP - point it at Honeycomb, Datadog, or any OTel-native backend by setting OTEL_EXPORTER_OTLP_ENDPOINT. The protocol attributes (session.id, agent.role, o2r.*) work everywhere; backend-specific UX (annotation configs in Phoenix, dashboards in Grafana) is added by extension packages.
Agents route through the cli-guard gate; see ../.ward/ward.yaml (the transition bridge ../.coily/coily.yaml runs locally today). Humans: make help for the full target list.
message/send- send a message, get a Task back. The originator setsmetadata.agent.id(sender) and optionallymetadata.agent.target(recipient).message/stream- same envelope, but the response istext/event-streamcarrying A2Astatus-update/artifact-updateevents; the relay emits onea2a.message.stream_chunkspan event per artifact.tasks/get- retrieve a Task by id from the relay's in-memory store.tasks/cancel- mark a Task canceled and emit ana2a.task.cancelspan.
The peer agent serves an A2A AgentCard at /.well-known/agent.json; the relay's GET /peers aggregates them for discovery.
- ../README.md - intro and overview.
- protocol.md - the span shape and the v0.1 decisions behind it.
- harness.md - validating the protocol against a real Phoenix.