Trace with Phoenix
PowerContext exports OpenTelemetry spans for transport and application operations. When tracing is enabled, the generation and embedding calls that PowerContext itself constructs are traced too, so one trace shows the request, the Memory operation, and the model calls underneath it.
This guide sends those spans to Phoenix running locally.
Start Phoenix
docker run -d --name powercontext-phoenix -p 6006:6006 arizephoenix/phoenix:20.1.0Phoenix serves both its UI and its OTLP HTTP receiver on port 6006. Open http://localhost:6006 to confirm it is
running. Pin an explicit tag so the endpoint and UI layout match this guide.
Install the export dependency
Recording and export require the tracing-otlp extra:
uv tool install --force "powercontext[cli,server,tracing-otlp] @ git+https://github.com/oceanbase/powercontext.git@master"Without this extra, enabling tracing fails at startup with an explicit error instead of silently dropping spans.
Configure and start the Server
Enable tracing, point the exporter at Phoenix, and configure a generation model so inference spans have something to record:
export POWERCONTEXT_SERVER_TRACING_ENABLED=true
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:6006
export OTEL_SERVICE_NAME=powercontext-server
export POWERCONTEXT_SERVER_INFERENCE_GENERATION_MODEL=provider:model-name
powercontext server runThe OpenTelemetry SDK appends /v1/traces to OTEL_EXPORTER_OTLP_ENDPOINT, so the spans arrive at
http://localhost:6006/v1/traces. Use OTEL_EXPORTER_OTLP_HEADERS for a Phoenix deployment that requires
authentication. Set the provider credentials your generation model needs; PowerContext never records them.
Trigger one inference request
Set POWERCONTEXT_SCOPE_ID to an existing ID returned by create_scope, capture a Source, then convert it into
Memory:
curl -X POST http://localhost:8000/v1/sources/content \
-H 'content-type: application/json' \
-d "{\"scope_id\":\"${POWERCONTEXT_SCOPE_ID}\",\"source_id\":\"task-1\",\"content\":\"I always book aisle seats.\"}"curl -X POST http://localhost:8000/v1/memory/flush \
-H 'content-type: application/json' \
-d "{\"scope_id\":\"${POWERCONTEXT_SCOPE_ID}\"}"Memory extraction runs during the flush, not during capture.
Read the trace
Open http://localhost:6006, select the default project, and open the most recent trace for
powercontext-server. The flush produces five nested spans in one trace:
| Span | Meaning |
|---|---|
HTTP flush_memory | The inbound HTTP request. powercontext.request.id matches the X-PowerContext-Request-ID response header. |
powercontext flush_memory | The application operation, independent of the transport that invoked it. |
memory.flush | The Runtime stage that processes the Source window. Inference spans nest beneath it when extraction runs. |
invoke_agent memory_extraction | One PowerContext generation task. The name identifies the purpose, not the model. |
chat <model> | One request to the model provider, with token usage and latency. |
Scoped operations add the following internal stage spans beneath their application operation. Read-only searches never
take the write lock, so they emit no scope.lock span:
| Span | Meaning |
|---|---|
scope.context | Resolving the scope's context from the configured provider; near zero for the built-in provider, visible when a provider does I/O here. |
scope.lock | Waiting for the scope write lock, ending the moment it is acquired. powercontext.scope.lock.contended reports whether another operation already held it. |
memory.flush | One Source-window flush for flush_memory or a scheduled activation. |
memory.search | Memory lookup for search_memory or prepare_context; embedding and reranking spans, when present, are nested beneath it. |
memory.rerank | One actual reranker call; model-backed reranking nests invoke_agent memory_rerank beneath it. |
experience.search | Experience recall during prepare_context; emitted even when recall is not configured. |
experience.incubation | One Experience incubation run for a scheduled activation. |
context.build | The synchronous step that selects and renders the final prepared context from recalled candidates. |
The other PowerContext generation tasks appear under the same convention: experience_incubation,
experience_generation, skill_generation, handoff_generation, and memory_rerank. When an embedding model is
configured, embedding calls appear as embeddings <model> spans under the operation that triggered them.
Spans are exported in batches, so allow a few seconds before refreshing. An MCP request produces
MCP mcp.tools.call in place of the HTTP span. Readiness probes are deliberately not traced, so health checks do not
create single-span traces.
Scheduled background spans
When a scheduler interval is configured (schedule_seconds or experience_schedule_seconds), each scheduled activation
starts its own trace instead of joining an unrelated request trace. The activation is the root span with
powercontext.operation.unit set to background:
| Span | Meaning |
|---|---|
scheduled.process_source_window | One scheduled Source-window activation. Its outcome is success, noop, failure, or cancelled. |
scheduled.incubate_experience_candidates | One scheduled Experience incubation activation, with the same outcome vocabulary. |
memory.flush | The flush run beneath a Source-window activation; it also appears under HTTP flush_memory. |
experience.incubation | The incubation run beneath an Experience activation. |
Scheduled roots record only bounded counts — powercontext.background.source_count and
powercontext.background.candidate_count — and never a scope_id, request ID, or Memory content. Inference spans created
by a scheduled activation are nested beneath its root in the same trace.
What is not exported
PowerContext configures inference instrumentation to exclude content. Spans carry model identifiers, token usage, durations, and error categories. Prompts, model responses, Memory content, and vectors are excluded, and message attributes record only the shape of each message rather than its text.
Stop Phoenix
docker rm -f powercontext-phoenixSpan names and attributes follow the Pydantic AI GenAI semantic conventions and can change when that dependency is upgraded across a major version. Do not treat them as a stable contract.

