Skip to content

fix: migrate subagent tracing hook - #142

Open
jleonelion wants to merge 2 commits into
comet-ml:mainfrom
jleonelion:fix/subagent-hook-api
Open

fix: migrate subagent tracing hook#142
jleonelion wants to merge 2 commits into
comet-ml:mainfrom
jleonelion:fix/subagent-hook-api

Conversation

@jleonelion

@jleonelion jleonelion commented Jul 26, 2026

Copy link
Copy Markdown

User description

Summary

  • Removes the deprecated api.on("subagent_spawning", ...) registration from the Opik OpenClaw plugin.
  • Creates and enriches Opik subagent lifecycle spans from the supported subagent_spawned hook instead, preserving label/requester/thread metadata.
  • Updates tests and the README event table to match the non-deprecated hook surface.

Risk: Medium — runtime observability hook behavior changes, but scope is limited to the Opik plugin subagent span lifecycle and covered by focused/full plugin tests.

Test plan

  • npm run test -- src/service.test.ts
  • npm run lint
  • npm run build
  • npm run test
  • npm run smoke
  • npm run typecheck
  • npm run pack:check

Gate and validation evidence

  • Pre-PR gate: decision=proceed, artifact /tmp/forge-loop/2026-07-26T1000Z-dev-sprint/pre-pr-gate-opik-openclaw.json
  • Protected-file decision: no protected files matched
  • Open-PR conflict decision: proceed, checked 0 open PRs
  • Changed-file count: 4
  • Verifier evidence: not applicable (no sessions_spawn helper used)
  • CI note: CI-will-verify (.github/workflows present).

Co-Authored-By: Forge noreply@openclaw.local


Generated description

Below is a concise technical summary of the changes proposed in this PR:

graph LR
plugin_("plugin"):::modified
registerOpikCli_("registerOpikCli"):::modified
OPENCLAW_CONFIG_index_ts_("OPENCLAW_CONFIG (index.ts)"):::modified
runOpikConfigure_("runOpikConfigure"):::modified
showOpikStatus_("showOpikStatus"):::modified
OPENCLAW_CONFIG_src_configure_ts_("OPENCLAW_CONFIG (src/configure.ts)"):::modified
registerHooks_("registerHooks"):::modified
OPENCLAW_API_src_service_ts_("OPENCLAW_API (src/service.ts)"):::modified
registerSubagentHooks_("registerSubagentHooks"):::modified
OPENCLAW_API_src_service_hooks_subagent_ts_("OPENCLAW_API (src/service/hooks/subagent.ts)"):::modified
OPIK_("OPIK"):::modified
plugin_ -- "Passes current config and mutation callback instead of file I/O." --> registerOpikCli_
plugin_ -- "Reads current config and mutates via runtime API; restart required." --> OPENCLAW_CONFIG_index_ts_
registerOpikCli_ -- "Supplies currentConfig and mutateConfig callbacks for configuration updates." --> runOpikConfigure_
registerOpikCli_ -- "Status reads configuration through currentConfig instead of loadConfig." --> showOpikStatus_
runOpikConfigure_ -- "Uses current snapshot and mutation callback to update Opik settings." --> OPENCLAW_CONFIG_src_configure_ts_
showOpikStatus_ -- "Reads current OpenClaw configuration via currentConfig for status display." --> OPENCLAW_CONFIG_src_configure_ts_
registerHooks_ -- "Sanitizes any event.message value, returning it only when transformed." --> OPENCLAW_API_src_service_ts_
registerSubagentHooks_ -- "Handles spawned events, capturing label, requester, thread, and run metadata." --> OPENCLAW_API_src_service_hooks_subagent_ts_
registerSubagentHooks_ -- "Creates spawned-status spans with richer request and session/run metadata." --> OPIK_
classDef added stroke:#15AA7A
classDef removed stroke:#CD5270
classDef modified stroke:#EDAC4C
linkStyle default stroke:#CBD5E1,font-size:13px
Loading

Migrate Opik subagent tracing from the deprecated subagent_spawning hook to subagent_spawned, preserving lifecycle metadata and span enrichment. Update OpenClawPluginApi, configuration commands, tests, documentation, and SDK entry-point integrations for the supported plugin APIs.

TopicDetails
Plugin SDK migration Adopt the split plugin-entry and diagnostic-runtime SDK surfaces, and migrate CLI configuration from whole-file writes to currentConfig plus mutateConfigFile.
Modified files (11)
  • .scripts/vitest-openclaw-plugin-sdk.mjs
  • index.ts
  • src/cli.ts
  • src/configure.test.ts
  • src/configure.ts
  • src/plugin.smoke.test.ts
  • src/service.ts
  • src/service/hooks/llm.ts
  • src/service/hooks/tool.ts
  • src/service/payload-sanitizer.ts
  • vitest.config.mjs
Latest Contributors(0)
UserCommitDate
Subagent tracing Create and enrich subagent lifecycle spans through subagent_spawned, retaining requester, label, thread, and run metadata while updating focused tests and event documentation.
Modified files (4)
  • README.md
  • src/service.e2e.test.ts
  • src/service.test.ts
  • src/service/hooks/subagent.ts
Latest Contributors(0)
UserCommitDate
Review this PR on Baz | Customize your next review

Use the non-deprecated subagent_spawned lifecycle hook to create Opik
subagent spans, preserving the metadata formerly captured during the
legacy subagent_spawning hook.

Co-Authored-By: Forge <noreply@openclaw.local>
Comment on lines 63 to +74
input: {
childSessionKey,
agentId: eventObj.agentId,
label: eventObj.label,
mode: eventObj.mode,
requester: eventObj.requester,
threadRequested: eventObj.threadRequested,
},
metadata: {
status: "spawned",
requesterSessionKey,
childSessionKey,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

delivery-target span reused as lifecycle

If childSessionKey was already used by subagent_delivery_target, subagent_spawned only updates the existing span's input and metadata, so it can stay recorded as subagent:delivery-target instead of the intended subagent:<agentId> lifecycle span — should we recreate or rename it here?

Severity

Want Baz to fix this for you? Activate Fixer

Other fix methods

Fix in Cursor

Prompt for AI Agents
Before applying, verify this suggestion against the current code. In
`src/service/hooks/subagent.ts` around lines 63-79 inside the
`deps.api.on("subagent_spawned", ...)` handler, the code reuses an existing span if one
exists (from earlier hooks like `subagent_delivery_target`) and only calls
`deps.safeSpanUpdate` for metadata, never recreating/renaming the span to the intended
`subagent:<agentId>` lifecycle semantics. Refactor this logic so that when
`subagent_spawned` fires and the current stored span was created for a different stage
(e.g., name/status mismatch), you end the old span (via the existing `deps.safeSpanEnd`
pattern if available), create a new span with `name: subagent:${agentId}` and the
intended `input` fields (childSessionKey, label, mode, requester, threadRequested),
replace `host.active.subagentSpans` and the remembered host association with the new
span, and then apply the `safeSpanUpdate` enrichment. Ensure the map always points at
the correct “spawned” span for that `childSessionKey` after this handler runs.

Comment thread index.ts
Comment on lines +1 to +6
import type {
OpenClawConfig,
OpenClawPluginApi,
OpenClawPluginDefinition,
} from "openclaw/plugin-sdk/plugin-entry";
import { definePluginEntry, emptyPluginConfigSchema } from "openclaw/plugin-sdk/plugin-entry";

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The openclaw/plugin-sdk/plugin-entry and diagnostic-runtime imports in src/service.ts use APIs unavailable in the minimum >=2026.3.2, while only openclaw/plugin-sdk has local declarations, so a clean checkout without the optional openclaw peer fails tsc/npm run build and the plugin cannot load or opik configure cannot save configuration. Should we declare those subpaths locally, retain compatibility fallbacks, or raise the minimum/peer gateway version?

Severity web_search

Want Baz to fix this for you? Activate Fixer

Other fix methods

Fix in Cursor

Prompt for AI Agents
Before applying, verify this suggestion against the current code. In `index.ts` around
lines 1-6 (and 29-35), reconcile the OpenClaw SDK imports and `register` configuration
logic with the declared `>=2026.3.2` / `minGatewayVersion` support: the `plugin-entry`
APIs (`OpenClawPluginDefinition`, `definePluginEntry`, `current()`,
`mutateConfigFile()`) and the `diagnostic-runtime` import used in `src/service.ts`
(`DiagnosticEventPayload`) are not available on that runtime and are not resolvable via
local type declarations. Either add ambient declarations for the
`openclaw/plugin-sdk/plugin-entry` and `openclaw/plugin-sdk/diagnostic-runtime` subpaths
(or make the external peer SDK declarations an explicit build prerequisite, since Vitest
aliases only affect tests) so a clean `npm run build` succeeds, and provide
compatibility fallbacks using older load/write configuration APIs; if backward
compatibility isn't feasible, raise the peer and minimum gateway version requirements in
the package manifest to the first release providing all of these APIs.

return proto === Object.prototype || proto === null;
}

export function sanitizeValueForOpik<T>(value: T): T;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Sanitizer returns invalid narrow types

The new sanitizeValueForOpik<T>(value: T): T overload claims identity even though sanitization rewrites nested strings and reconstructs arrays/plain objects, so a const value: "media:/tmp/x.png" result can be "media:<image-ref>" while callers still use it as the original literal — should we return a widened sanitized type or remove the identity overload?

Severity

Want Baz to fix this for you? Activate Fixer

Other fix methods

Fix in Cursor

Prompt for AI Agents
Before applying, verify this suggestion against the current code. In
src/service/payload-sanitizer.ts around line 30, fix the `sanitizeValueForOpik` overload
because it promises the original type even though the implementation rewrites strings
and reconstructs nested arrays and plain objects. Remove the identity overload or
replace it with a sound widened/recursive sanitized return type, then update affected
call sites and tests so redacted string literals and precisely shaped or readonly
payloads are not treated as unchanged.

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