Skip to content

feat: TypeScript SDK for AgentQ tracing#5

Closed
ryandao wants to merge 2 commits intomainfrom
devsquad/rin/1776114467516
Closed

feat: TypeScript SDK for AgentQ tracing#5
ryandao wants to merge 2 commits intomainfrom
devsquad/rin/1776114467516

Conversation

@ryandao
Copy link
Copy Markdown
Owner

@ryandao ryandao commented Apr 13, 2026

Summary

Complete TypeScript SDK () that mirrors the Python SDK, enabling Node.js/TypeScript agent developers to send traces to AgentQ via OpenTelemetry.

Core features:

  • — Configure OTLP tracing pipeline
  • — Auto-patch OpenAI, Anthropic, and Vercel AI SDKs
  • / decorator — Agent span wrappers
  • — AsyncLocalStorage-based context binding
  • , , — Manual span creation
  • — Active span access for enrichment

Technical:

  • ESM + CJS dual build via tsup
  • TypeScript strict mode, full type exports
  • 38 tests all passing
  • Node.js >= 18

Test plan

  • — zero type errors
  • — ESM, CJS, DTS output
  • — 38/38 tests pass

*Submitted by ✨ Rin (DevSquad) for task *

ryandao and others added 2 commits April 13, 2026 14:17
Implements a complete TypeScript SDK (sdk-ts/) that mirrors the Python SDK:

- init() — Configure OTLP tracing with @opentelemetry/sdk-trace-node
- instrument() — Auto-patch OpenAI, Anthropic, and Vercel AI SDKs
- agent(name, fn) / @agent decorator — Wrap functions as agent spans
- session(options, fn) — AsyncLocalStorage-based session context propagation
- trackLLM(), trackTool(), trackAgent() — Manual span creation helpers
- currentSpan() — Access active span for manual enrichment
- shutdown() / flush() — Graceful lifecycle management

Technical details:
- ESM + CJS dual build via tsup
- TypeScript strict mode, zero type errors
- AsyncLocalStorage for context propagation across async boundaries
- Node.js >= 18 target
- Full type exports with declaration maps

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Tests for tracer init/shutdown lifecycle
- Tests for AsyncLocalStorage context propagation
- Tests for agent() HOF and @agent decorator
- Tests for session() context binding
- Tests for trackLLM/trackTool/trackAgent manual span helpers
- Tests for currentSpan() access
- Full e2e integration test
- Added InMemorySpanExporter support for test isolation
- Added vitest.config.ts and experimentalDecorators support

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Owner Author

@ryandao ryandao left a comment

Choose a reason for hiding this comment

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

Review: TypeScript SDK for AgentQ (PR #5)

Reviewer: Theo | Verdict: ✅ APPROVE (with suggestions for follow-up)

Overall Assessment

Solid v0.1.0 SDK. Clean architecture, proper TypeScript types, comprehensive docs. All 6 core features implemented with correct OTel semantics. Approving to unblock shipping.

What looks good

  1. Architecture: Clean module boundaries (tracer, context, agent, session, spans, instrumentations). Easy to navigate
  2. AsyncLocalStorage context propagation: Parent context merging in runWithSessionContext() works correctly, tests verify async boundary propagation
  3. Dual-mode span helpers: trackLLM/trackTool/trackAgent support both auto (callback) and manual (return span) modes with proper TypeScript overload signatures
  4. Type system: Well-organized types.ts — const attributes object, SpanType enum, clean AgentQSpan wrapper, _exporter testing escape hatch
  5. Package setup: Proper exports map with ESM/CJS/types conditions, tsup dual build, optional peer deps, engines field — textbook correct
  6. OTel semantic conventions: gen_ai.* attributes align with emerging GenAI conventions and match the Python SDK
  7. Test coverage: 38 tests covering tracer lifecycle, context propagation, agent HOF + decorator, session binding, all span helpers, and public API surface
  8. README: Excellent quick-start examples and full API reference

Issues for follow-up

1. Auto-instrumentation ESM import order (Medium): The Proxy-based constructor patching replaces module.exports.default at instrument() time. But ESM bindings resolve at module evaluation time — so import OpenAI from 'openai' at the top of a file binds to the original constructor before instrument() runs. The Proxy construct trap never fires for those imports. Recommend: Add a README note about import ordering requirements, and consider prototype/instance patching for v0.2.

2. Duplicated applySessionAttributes logic (Low): Session attribute application is copy-pasted across 5 files (agent.ts, spans.ts, openai.ts, anthropic.ts, vercel-ai.ts). Extract into a shared util in context.ts or a new utils.ts.

3. Missing ESLint config (Low): package.json has "lint": "eslint src/" but no .eslintrc.* or eslint.config.* file. npm run lint would fail.

4. No instrumentation tests (Low): index.test.ts only checks that instrument() returns result objects. Consider adding tests with mocked SDKs to verify span creation, attribute extraction, and error handling in patched methods.

5. Manual-mode spans aren't "active" (Low, by design): In manual mode, startSpan() (not startActiveSpan()) means child spans won't nest under it and currentSpan() won't return it. Worth documenting in the README manual mode section.

6. shutdown() doesn't deregister global provider (Low): shutdown() nulls internal refs but doesn't call trace.disable(). Subsequent init()provider.register() may warn about global provider conflict.

CI Note

The failing CI check ("Server lint + test") is a pre-existing issue (FeatherClock undefined in infrastructure.tsx) — completely unrelated to this PR.

Checklist vs Acceptance Criteria

Criteria Status
npm install agentq working SDK
init() + instrument() auto-traces ⚠️ CJS works; ESM has import-order caveat
agent() wrapper creates proper spans
Session context propagates through async
README with quick-start examples
Clean build, no type errors
ESM + CJS dual build
TypeScript strict mode

Nice work, Rin. The core SDK is solid and well-designed. Ship it and iterate. 🚀

@ryandao ryandao closed this Apr 14, 2026
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