[TypeScript SDK] Add opik-agentica integration package#5430
[TypeScript SDK] Add opik-agentica integration package#5430vincentkoc wants to merge 19 commits intomainfrom
Conversation
📋 PR Linter Failed❌ Invalid Title Format. Your PR title must include a ticket/issue number and may optionally include component tags (
Example: ❌ Incomplete Issues Section. You must reference at least one GitHub issue ( |
| const attachUsageCollectorToArgs = ( | ||
| methodName: string, | ||
| args: unknown[], | ||
| onUsage: (usage: Record<string, number> | undefined) => void | ||
| ): unknown[] => { | ||
| if (methodName !== "agentic" && methodName !== "agenticTransformation") { | ||
| return args; | ||
| } | ||
|
|
||
| const nextArgs = [...args]; | ||
| const configIndex = typeof nextArgs[1] === "object" && nextArgs[1] !== null ? 2 : 1; | ||
| const currentConfig = nextArgs[configIndex]; | ||
|
|
||
| if (typeof currentConfig === "object" && currentConfig !== null) { | ||
| const configObject = currentConfig as Record<string, unknown>; | ||
| const previousOnUsage = configObject.onUsage; | ||
|
|
||
| nextArgs[configIndex] = { | ||
| ...configObject, | ||
| onUsage: (usage: unknown) => { | ||
| onUsage(parseUsage(usage)); | ||
| if (typeof previousOnUsage === "function") { | ||
| (previousOnUsage as (value: unknown) => void)(usage); | ||
| } | ||
| }, | ||
| }; | ||
| return nextArgs; | ||
| } | ||
|
|
||
| nextArgs[configIndex] = { | ||
| onUsage: (usage: unknown) => onUsage(parseUsage(usage)), | ||
| }; |
There was a problem hiding this comment.
configIndex assumes args[1] is a scope when it is present, so (prompt, config) calls detect an object at args[1] and set configIndex = 2; the existing config remains at index 1 and onUsage is written to a new argument slot, leaving the real config without the hook and preventing usage events from ever firing for that signature. Can we detect the (prompt, config) signature and inject onUsage into index 1 instead?
Finding type: Logical Bugs
Want Baz to fix this for you? Activate Fixer
Other fix methods
Prompt for AI Agents:
In sdks/typescript/src/opik/integrations/opik-agentica/src/decorators.ts around lines 29
to 60, the attachUsageCollectorToArgs function incorrectly sets configIndex = 2 whenever
args[1] is an object, which breaks the (prompt, config) signature by placing the onUsage
hook at the wrong slot. Change the configIndex detection so that if args[0] is a prompt
(e.g., a string) and args[1] is an object, set configIndex = 1; otherwise if args[2] is
an object set configIndex = 2; otherwise default to 1. Apply this conditional
assignment, keep the rest of the onUsage injection logic intact, and ensure existing
behavior for other signatures is preserved.
| import { Opik, OpikConfig } from "opik"; | ||
|
|
||
| export class OpikSingleton { | ||
| private static instance: Opik | null = null; | ||
|
|
||
| public static getInstance(params?: Partial<OpikConfig>): Opik { | ||
| if (!OpikSingleton.instance) { | ||
| OpikSingleton.instance = new Opik(params); | ||
| } | ||
| return OpikSingleton.instance; | ||
| } |
There was a problem hiding this comment.
OpikSingleton here is verbatim to the singleton in opik-openai/src/singleton.ts and opik-gemini/src/singleton.ts, so every change has to be copied across integrations; can we extract a shared OpikSingleton module under src/opik/integrations/shared and import it instead of duplicating?
Finding type: Code Dedup and Conventions
Want Baz to fix this for you? Activate Fixer
| const config: TracingConfig = { | ||
| ...opikConfig, | ||
| generationName: createGenerationName( | ||
| sdk, | ||
| methodName, |
There was a problem hiding this comment.
config.generationName is always set to createGenerationName(..., opikConfig?.generationName) before any method call, and the same config (with that explicit name) is passed down when wrapping nested results (trackAgentica(..., config, cache)); nested agents therefore never recompute the method-specific name and every span inherits the parent property's generationName (e.g. Agentica.spawn for agent.call). Can we avoid carrying the parent generationName into recursive wraps so each method can use its own default name?
Finding type: Logical Bugs
Want Baz to fix this for you? Activate Fixer
Other fix methods
Prompt for AI Agents:
In sdks/typescript/src/opik/integrations/opik-agentica/src/trackAgentica.ts around lines
66 to 70 (the Proxy get handler / traced-method logic), the current code builds a
per-method TracingConfig (with generationName) and then passes that same config into
recursive wrapping, causing nested agents to inherit the parent's generationName.
Refactor so recursive wraps do not receive the per-method TracingConfig: change the
calls that currently pass 'config' into trackAgentica and wrapResultIfNeeded (the
Promise.then branch and the synchronous wrap return, and the branch that wraps nested
object properties) to pass the original TrackOpikConfig parameter 'opikConfig' (or a
shallow copy with generationName unset) instead. This ensures nested proxies recompute
their own generationName per method rather than inheriting the parent one.
Details
sdks/typescript/src/opik/integrations/opik-agenticatrackAgentica(...)as a proxy wrapper for Agentica SDK call paths (spawn,agentic,call, and transformation variants)prompt_tokens,completion_tokens,total_tokens)sdks/typescript/README.mdsdks/typescript/design/INTEGRATIONS.mdsdks/typescript/tsconfig.jsonexcludes.github/workflows/typescript_sdk_integration_publish.ymlmatrix.github/workflows/release.yamlversion bump loopChange checklist
Issues
Testing
cd sdks/typescript/src/opik/integrations/opik-agentica && npm installcd sdks/typescript/src/opik/integrations/opik-agentica && npm run lintcd sdks/typescript/src/opik/integrations/opik-agentica && npm run typecheckcd sdks/typescript/src/opik/integrations/opik-agentica && npm run testcd sdks/typescript/src/opik/integrations/opik-agentica && npm run buildDocumentation
opik-agentica.