Conversation
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>
ryandao
left a comment
There was a problem hiding this comment.
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
- Architecture: Clean module boundaries (tracer, context, agent, session, spans, instrumentations). Easy to navigate
- AsyncLocalStorage context propagation: Parent context merging in
runWithSessionContext()works correctly, tests verify async boundary propagation - Dual-mode span helpers:
trackLLM/trackTool/trackAgentsupport both auto (callback) and manual (return span) modes with proper TypeScript overload signatures - Type system: Well-organized
types.ts— const attributes object,SpanTypeenum, cleanAgentQSpanwrapper,_exportertesting escape hatch - Package setup: Proper
exportsmap with ESM/CJS/types conditions,tsupdual build, optional peer deps, engines field — textbook correct - OTel semantic conventions:
gen_ai.*attributes align with emerging GenAI conventions and match the Python SDK - Test coverage: 38 tests covering tracer lifecycle, context propagation, agent HOF + decorator, session binding, all span helpers, and public API surface
- 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 |
|
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. 🚀
Summary
Complete TypeScript SDK () that mirrors the Python SDK, enabling Node.js/TypeScript agent developers to send traces to AgentQ via OpenTelemetry.
Core features:
Technical:
Test plan
*Submitted by ✨ Rin (DevSquad) for task *