Skip to content

fix(agents): snapshot session tool definitions#91293

Closed
vincentkoc wants to merge 2 commits into
mainfrom
split-agent-session-tool-snapshots-20260608
Closed

fix(agents): snapshot session tool definitions#91293
vincentkoc wants to merge 2 commits into
mainfrom
split-agent-session-tool-snapshots-20260608

Conversation

@vincentkoc

Copy link
Copy Markdown
Member

Summary

  • Snapshots session tool definitions and registered extension tool definitions before agent runtime paths normalize or execute them.
  • Quarantines unreadable schema/name values while preserving healthy sibling tools and existing execution/error behavior.
  • Cherry-picked from the superseded large split stack in fix(runtime): snapshot tool definitions #90411: b4cc7c792c9 and 8c92f6bc055.

Verification

  • node scripts/run-vitest.mjs run src/agents/agent-tool-definition-adapter.test.ts src/agents/sessions/extensions/loader.test.ts src/agents/sessions/sdk.test.ts src/agents/sessions/tools/tool-definition-wrapper.test.ts --reporter=dot
  • ./node_modules/.bin/oxfmt --check src/agents/agent-tool-definition-adapter.test.ts src/agents/agent-tool-definition-adapter.ts src/agents/sessions/agent-session.ts src/agents/sessions/extensions/loader.test.ts src/agents/sessions/extensions/loader.ts src/agents/sessions/sdk.test.ts src/agents/sessions/sdk.ts src/agents/sessions/tools/tool-definition-wrapper.test.ts src/agents/sessions/tools/tool-definition-wrapper.ts
  • OPENCLAW_OXLINT_SKIP_PREPARE=1 node scripts/run-oxlint.mjs --tsconfig config/tsconfig/oxlint.core.json src/agents/agent-tool-definition-adapter.test.ts src/agents/agent-tool-definition-adapter.ts src/agents/sessions/agent-session.ts src/agents/sessions/extensions/loader.test.ts src/agents/sessions/extensions/loader.ts src/agents/sessions/sdk.test.ts src/agents/sessions/sdk.ts src/agents/sessions/tools/tool-definition-wrapper.test.ts src/agents/sessions/tools/tool-definition-wrapper.ts
  • git diff --check
  • .agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main

Behavior addressed

  • Session and extension-registered tool definitions are copied at the boundary so later schema/name getter failures or mutations cannot break unrelated healthy tools.

Real environment tested

  • macOS linked OpenClaw worktree with shared install and focused Vitest/lint/format checks.

Exact steps or command run after this patch

  • Ran the focused commands listed in Verification after cherry-picking the agent/session snapshot commits.

Evidence after fix

  • 34 focused tests passed across agent tool definition adaptation, session SDK custom tools, extension loader registration, and session tool wrapping.
  • Focused format, core oxlint, whitespace check, and autoreview passed.

Observed result after fix

  • Bad session/extension tool schema or name access is quarantined locally, while healthy tools remain registered and callable.

What was not tested

  • Broad pnpm check:changed was not run locally because this is a linked/sparse worktree and disk is currently tight; PR CI should cover the wider gate.

@openclaw-barnacle openclaw-barnacle Bot added agents Agent runtime and tooling size: L maintainer Maintainer-authored PR labels Jun 8, 2026
@clawsweeper

clawsweeper Bot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs changes before merge. Reviewed June 25, 2026, 10:37 PM ET / 02:37 UTC.

Summary
The branch snapshots agent/session, base override, SDK custom, and extension-registered tool definitions so unreadable descriptors are quarantined while healthy sibling tools remain usable.

PR surface: Source +410, Tests +294. Total +704 across 9 files.

Reproducibility: yes. Source inspection gives a high-confidence path: construct an AgentTool or ToolDefinition with throwing name/parameters getters and call toToolDefinitions(), createAgentSession(), or extension registerTool(); I did not execute that repro in this read-only review.

Review metrics: 1 noteworthy metric.

  • Tool ingress behavior changed: 3 ingress paths changed. Agent adapter, session/base custom tools, and extension registerTool all move malformed descriptors toward per-tool quarantine, which is the central compatibility decision before merge.

Stored data model
Persistent data-model change detected: serialized state: src/agents/sessions/extensions/loader.test.ts, serialized state: src/agents/sessions/extensions/loader.ts, serialized state: src/agents/sessions/sdk.test.ts, serialized state: src/agents/sessions/sdk.ts, serialized state: src/agents/sessions/tools/tool-definition-wrapper.test.ts, serialized state: src/agents/sessions/tools/tool-definition-wrapper.ts, and 4 more. Confirm migration or upgrade compatibility proof before merge.

Merge readiness
Overall: 🧂 unranked krab
Proof: 🦞 diamond lobster
Patch quality: 🧂 unranked krab
Result: blocked by patch quality or review findings.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • Preserve current-main prepareArguments and executionMode behavior in the adapter snapshot path.
  • Replace unsafe String(err) fallbacks with no-throw formatting and hostile thrown-value regression tests.
  • Refresh the conflicting branch against current main before another merge-readiness review.

Risk before merge

  • [P1] The PR intentionally changes malformed plugin/custom/base tool handling from direct fail-fast descriptor reads to per-tool quarantine, which is a compatibility decision for existing invalid-tool setups.
  • [P1] The new skipped-tool logging can still throw while formatting hostile non-Error thrown values, allowing a malformed descriptor to abort registration or adaptation instead of being contained.
  • [P1] The live branch is conflicting/dirty against main; the refreshed merge result must preserve current-main prepareArguments and executionMode behavior before it is trustworthy.

Maintainer options:

  1. Fix snapshot blockers before merge (recommended)
    Refresh the branch, preserve current-main prepareArguments and executionMode metadata, and replace unsafe String(err) fallback paths with no-throw formatting plus hostile-thrown-value tests.
  2. Accept quarantine semantics explicitly
    Maintainers can choose the fail-fast to per-tool quarantine behavior after the mechanical blockers are fixed, but the upgrade impact should be named in the PR before merge.
  3. Prefer a narrower sibling path
    If this combined branch remains hard to refresh safely, continue with a clean narrower sibling PR and close this one only after a viable replacement owns the session-tool slice.
Copy recommended automerge instruction
@clawsweeper automerge

Special instructions:
Preserve current-main prepareArguments and executionMode in the AgentTool snapshot output, replace unsafe String(err) fallbacks in the session and AgentTool snapshot error describers with no-throw formatting, add regression tests for non-Error thrown values whose string conversion throws, and refresh the branch against current main without dropping current adapter metadata.

Next step before merge

  • [P2] A narrow automated repair can address the metadata preservation and no-throw formatter defects, while maintainer review still owns the compatibility decision and final merge approval.

Security
Needs attention: The diff improves malformed tool isolation, but the new skipped-tool logging can still let hostile thrown values escape the intended containment path.

Review findings

  • [P1] Preserve tool metadata in adapter snapshots — src/agents/agent-tool-definition-adapter.ts:396-400
  • [P2] Use no-throw formatting for skipped-tool errors — src/agents/sessions/tools/tool-definition-wrapper.ts:31
Review details

Best possible solution:

Refresh the branch against current main, keep the snapshot-boundary design, preserve current metadata contracts, replace unsafe error formatting with no-throw formatting, and have maintainers explicitly accept the per-tool quarantine compatibility change.

Do we have a high-confidence way to reproduce the issue?

Yes. Source inspection gives a high-confidence path: construct an AgentTool or ToolDefinition with throwing name/parameters getters and call toToolDefinitions(), createAgentSession(), or extension registerTool(); I did not execute that repro in this read-only review.

Is this the best way to solve the issue?

No as written. Snapshotting at the session/tool boundary is the right fix shape, but this implementation needs metadata preservation, no-throw error formatting, and an explicit maintainer compatibility decision first.

Full review comments:

  • [P1] Preserve tool metadata in adapter snapshots — src/agents/agent-tool-definition-adapter.ts:396-400
    Current main and its adjacent test preserve prepareArguments and executionMode when toToolDefinitions() mirrors an AgentTool, but this snapshot return only carries name/label/description/parameters. A refreshed merge would silently drop argument preparation and sequential execution metadata for tools using this adapter.
    Confidence: 0.9
  • [P2] Use no-throw formatting for skipped-tool errors — src/agents/sessions/tools/tool-definition-wrapper.ts:31
    The new quarantine catch falls back to String(err) for non-Error thrown values. A malformed plugin or custom tool getter can throw an object whose string conversion also throws, making the catch throw instead of skipping only the bad tool; use a no-throw formatter here and in the matching adapter helper.
    Confidence: 0.9

Overall correctness: patch is incorrect
Overall confidence: 0.9

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 6830aa39eaa1.

Label changes

Label justifications:

  • P2: This is a bounded agent/session robustness fix with concrete blockers and compatibility review needs, but the blast radius is limited to tool-definition ingress paths.
  • merge-risk: 🚨 compatibility: The branch changes malformed plugin/custom/base tool handling from fail-fast direct reads to per-tool quarantine, affecting existing plugin and session behavior.
  • merge-risk: 🚨 security-boundary: The diff is meant to contain hostile tool descriptors, but unsafe error formatting can still let hostile thrown values escape the containment path.
  • merge-risk: 🚨 availability: A malformed tool can still abort registration or adaptation through the PR's new catch path when stringifying a hostile thrown value fails.
  • rating: 🧂 unranked krab: Overall readiness is 🧂 unranked krab; proof is 🦞 diamond lobster and patch quality is 🧂 unranked krab.
  • status: ⏳ waiting on author: ClawSweeper has contributor-facing work open and is waiting for author action. Not applicable: The external-contributor proof gate does not apply to this member-authored PR, though the body includes focused local Vitest, lint, format, and autoreview proof.
Evidence reviewed

PR surface:

Source +410, Tests +294. Total +704 across 9 files.

View PR surface stats
Area Files Added Removed Net
Source 5 443 33 +410
Tests 4 294 0 +294
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 9 737 33 +704

Security concerns:

  • [medium] Hostile thrown value can escape quarantine logging — src/agents/sessions/tools/tool-definition-wrapper.ts:31
    A plugin-owned getter can throw a non-Error value whose string conversion throws; the new catch then throws while building the skip log message, turning a recoverable malformed-tool quarantine into a registration or adaptation failure.
    Confidence: 0.84

Acceptance criteria:

  • [P1] node scripts/run-vitest.mjs run src/agents/agent-tool-definition-adapter.test.ts src/agents/sessions/tools/tool-definition-wrapper.test.ts --reporter=dot.
  • [P1] git diff --check.
  • [P1] .agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main.

What I checked:

  • Repository policy applied: Root AGENTS.md and scoped src/agents/AGENTS.md were read fully; their review guidance makes agent/session runtime, plugin API behavior, and compatibility-sensitive fail-closed changes relevant to this verdict. (AGENTS.md:10, 6830aa39eaa1)
  • Current main lacks the central snapshot behavior: Current main still maps tools by directly reading tool.name, tool.label, tool.description, tool.parameters, prepareArguments, and executionMode in toToolDefinitions(). (src/agents/agent-tool-definition-adapter.ts:363, 6830aa39eaa1)
  • Current main preserves adapter metadata: The current adapter preserves prepareArguments and executionMode, and the adjacent current-main test asserts that contract for sequential tools. (src/agents/agent-tool-definition-adapter.test.ts:55, 6830aa39eaa1)
  • PR head drops adapter metadata: The PR-head snapshot return for toToolDefinitions() includes name, label, description, parameters, and execute, but does not carry prepareArguments or executionMode into the ToolDefinition. (src/agents/agent-tool-definition-adapter.ts:396, 1c7b5aa10a67)
  • PR head unsafe error formatting: The new skipped-tool error formatter falls back to String(err), so a non-Error thrown value with hostile string conversion can escape the intended quarantine path. (src/agents/sessions/tools/tool-definition-wrapper.ts:27, 1c7b5aa10a67)
  • Live PR state: Live GitHub metadata shows the PR is open, maintainer-labeled, mergeable CONFLICTING / DIRTY, and still on head 1c7b5aa. (1c7b5aa10a67)

Likely related people:

  • vincentkoc: Recent current-main commits touched agent tool adapter exports, and this PR is cherry-picked from the same author's larger hardening stack. (role: recent adjacent contributor and likely follow-up owner; confidence: high; commits: b832dd27e1cc, e7e686db2d00, 815a7c0ff862; files: src/agents/agent-tool-definition-adapter.ts, src/agents/sessions/sdk.ts, src/agents/sessions/tools/tool-definition-wrapper.ts)
  • steipete: GitHub history shows steipete authored the major agent runtime internalization and session tool documentation commits that shaped the affected session/tool wrapper surfaces. (role: current base surface history holder; confidence: high; commits: bb46b79d3c14, 600a57e60f1e, 60e0d2a7b910; files: src/agents/agent-tool-definition-adapter.ts, src/agents/sessions/tools/tool-definition-wrapper.ts, src/agents/sessions/extensions/loader.ts)
  • fuller-stack-dev: Recent current-main history includes adjacent tool-search directory mode work in the same adapter surface and tool-schema flow. (role: adjacent tool-schema contributor; confidence: medium; commits: 965fa05df38b; files: src/agents/agent-tool-definition-adapter.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

@clawsweeper clawsweeper Bot added rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. P2 Normal backlog priority with limited blast radius. labels Jun 8, 2026
@clawsweeper clawsweeper Bot added merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. merge-risk: 🚨 availability 🚨 May cause crashes, hangs, restart loops, stalls, or process outages. labels Jun 19, 2026
@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. and removed rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. labels Jun 21, 2026
@steipete

steipete commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Closing this one. This is a 737-line carryover from a superseded fuzz stack, with no user report and only synthetic getter/mutation cases across typed session and extension tool definitions.

Deep schema cloning, accessor evaluation, rebinding, and quarantine across nine files is disproportionate and changes the SDK/session contract. A real untyped ingress bug should be fixed narrowly at that boundary. Thanks for consolidating the earlier experiments.

@steipete steipete closed this Jul 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling maintainer Maintainer-authored PR merge-risk: 🚨 availability 🚨 May cause crashes, hangs, restart loops, stalls, or process outages. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. P2 Normal backlog priority with limited blast radius. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. size: L status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants