Skip to content

Add opt-in AgentPond tracing for simulation LLM calls - #17

Closed
marcusschiesser wants to merge 2 commits into
YGYOOO:mainfrom
marcusschiesser:agentpond-tracing
Closed

Add opt-in AgentPond tracing for simulation LLM calls#17
marcusschiesser wants to merge 2 commits into
YGYOOO:mainfrom
marcusschiesser:agentpond-tracing

Conversation

@marcusschiesser

Copy link
Copy Markdown

What changed

  • add opt-in OpenInference tracing around WorldX's real LLMClient.call() path
  • export server-side spans directly through AgentPond's Files SDK adapter
  • add a mock-provider E2E test and bilingual setup documentation
  • install the AgentPond skills generated by npx agentpond init

This fits WorldX's OpenAI-compatible simulation client without changing its request, retry, structured-output, or cost-tracking behavior.

Configuration and privacy

Tracing is disabled unless AGENTPOND_ENABLED=true. Storage is selected entirely through Files SDK environment variables, so no credentials or backend details are committed. Spans contain the OpenInference kind, model, WorldX task type, status/errors, and token counts. They intentionally omit prompts, responses, API keys, character identifiers, and tool payloads.

The filesystem adapter documented in the README is for local verification; production deployments should choose a persistent Files SDK provider.

Validation

Installed all declared workspaces with Node 22.22.1:

npm install

Checks:

npm run build --prefix client
npm run typecheck --prefix server
AGENTPOND_ENABLED=true npm run test:agentpond-e2e --prefix server

All passed. The E2E test ran the production LLMClient.call() against a local OpenAI-compatible HTTP server, verified the /v1/chat/completions request and parsed application result, then flushed the real AgentPond exporter.

Trace read-back:

npx agentpond sync --json
# objectsProcessed: 1, eventsProcessed: 2
npx agentpond traces get 8d4511cffdfa18b17d91541a1b745536 --json
npx agentpond observations list --traceId 8d4511cffdfa18b17d91541a1b745536 --json

The trace contained one generation-create observation named worldx.llm.call, model worldx-e2e-model, task agentpond-e2e, and token counts 9 prompt / 4 completion / 13 total. Its input and output fields were both null as intended.

Existing npm audit findings were left unchanged; this PR does not weaken or skip any test.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d1e44f0f0b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread server/src/telemetry/agentpond.ts Outdated
} catch (error) {
const exception =
error instanceof Error ? error : new Error(String(error));
span.recordException(exception);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Sanitize provider errors before exporting them

When an LLM provider returns a non-2xx response, sendRequest includes its entire response body in the thrown error, and recordException(exception) persists that message and stack in AgentPond. Providers may echo prompt fragments or generated content in error bodies, so this violates the documented guarantee that tracing does not record prompts or responses; export only a sanitized error category/status instead.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 0062ca6. Error spans now export only the fixed category LLMOperationError and status message LLM operation failed; the original provider error still propagates to application code but is never recorded on the span. The E2E fixture returns an error body containing a private prompt and asserts that neither the prompt nor echoed body exists in the raw Files SDK object. AgentPond read back sanitized error trace fe6ce0e9b0df0f9b1289deb82399e503.

Comment on lines +37 to +39
process.once("beforeExit", () => {
void shutdownAgentPond();
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Flush spans on termination signals

For long-running deployments stopped with SIGTERM or SIGINT (such as containers and service managers), Node exits without emitting beforeExit, so shutdownAgentPond() is never called and any spans still queued by BatchSpanProcessor are lost. Register shutdown handling at the server's actual signal lifecycle boundary and await it before exiting.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 0062ca6. AgentPond now registers one-shot SIGINT/SIGTERM handlers, awaits SDK shutdown, logs any flush failure, and then re-sends the original signal so the normal signal exit status is preserved. A production-module signal check exited with SIGTERM status 143 and wrote the queued trace object before termination.

assert.equal(requests.length, 1);
assert.equal(requests[0].url, "/v1/chat/completions");
assert.equal(requests[0].authorization, "Bearer test-key");
assert.equal(requests[0].body.model, "worldx-e2e-model");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Assert the trace in the end-to-end test

This test only flushes the processor and then checks the mock LLM request; it never reads the configured filesystem store or asserts that a span was exported. If exporter initialization or asynchronous export fails, tracing falls back or the batch processor swallows the export failure and every current assertion still passes, so the test does not verify the behavior named by the test.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 0062ca6. The E2E test now recursively reads the configured filesystem store (excluding adapter metadata), parses every exported batch, and asserts the two expected spans, trace IDs, model/token attributes, sanitized error status, and absence of prompts/provider bodies. The current AgentPond CLI then synced 1 object / 4 events and read back success trace 0e0258c91dab0a6aa1c17964dada6ccd plus sanitized error trace fe6ce0e9b0df0f9b1289deb82399e503.

@marcusschiesser

Copy link
Copy Markdown
Author

Closing this because I submitted the AgentPond integration before confirming it was wanted. I’m switching to a permission-first approach and don’t want to leave unsolicited review work in your queue. Sorry for the noise; I’ll only revisit if a maintainer explicitly invites it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant