fix(gateway): tolerate Paperclip metadata via adapterMeta namespace + paperclip alias on AgentParamsSchema#74974
Conversation
|
Thanks for the context here. I swept through the related work, and this is now duplicate or superseded. Keep open, but this PR is not merge-ready: the Paperclip gateway rejection still appears unsolved on current main, while this branch edits the removed Root-cause cluster Members:
Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything. Canonical path: Close this stale PR. The latest review rated it F, the branch still lacks merge-ready proof, and there has been no human follow-up after the durable review. So I’m closing this here because the remaining work is already tracked in the canonical issue. Review detailsBest possible solution: Close this stale PR. The latest review rated it F, the branch still lacks merge-ready proof, and there has been no human follow-up after the durable review. Do we have a high-confidence way to reproduce the issue? Yes, source-level: current main validates Is this the best way to solve the issue? No, not as submitted: the namespace-plus-alias direction is plausible, but the patch targets a removed protocol path and changes a public wire contract. The best fix needs the current package path, generated artifacts, and maintainer agreement on the API shape. Security review: Security review cleared: No concrete security or supply-chain issue was found; the diff does not add dependencies, scripts, workflows, or secret handling, and the proposed metadata is ignored after validation. AGENTS.md: found and applied where relevant. What I checked:
Likely related people:
Codex review notes: model internal, reasoning high; reviewed against be94853de0d0. |
…tadata The first commit on this branch added `paperclip: Type.Optional(Type.Unknown())` to AgentParamsSchema as a vendor-named root-level tolerance field. The review on openclaw#74974 (and the surrounding history of openclaw#62102, openclaw#74635, openclaw#72565, openclaw#69139, openclaw#75901 — three earlier PRs proposing the same vendor-named shape, all closed without merge) makes the underlying request clear: the right contract is a generic opaque-metadata namespace any external agent or plugin adapter can write under, not a name-per-vendor field that grows the gateway protocol surface every time a new adapter ships. This commit lands that namespace alongside the existing alias: - AgentParamsSchema gains `adapterMeta: Type.Optional(Type.Record( Type.String(), Type.Unknown()))`. Each adapter writes its own top-level key under it (`adapterMeta: { paperclip: {...}, greptile: {...} }`); the gateway accepts the bag as opaque and never inspects it. - The existing `paperclip: Type.Optional(Type.Unknown())` field is kept as a backward-compatibility alias, with a comment documenting that new adapter metadata should use `adapterMeta` and that this field can be removed once the published Paperclip adapter cuts a release that nests its payload under `adapterMeta.paperclip`. Heartbeats from current Paperclip releases keep dispatching during the transition. - `additionalProperties: false` on AgentParamsSchema is left intact, so a typo'd root field (e.g. `idempotnecyKey`) still fails validation before dispatch — the fix doesn't widen the schema, it just adds two named landing pads. Tests in src/gateway/protocol/agent-params-validator.test.ts now cover: - adapterMeta with multiple adapter keys (paperclip + greptile) accepted - empty adapterMeta and adapterMeta with primitive values accepted - both surfaces side by side (paperclip + adapterMeta.paperclip) accepted - adapterMeta with a non-object value rejected - existing paperclip-only path unchanged - truly unknown root properties still rejected - canonical message + idempotencyKey still required Swift bindings in apps/shared/OpenClawKit/Sources/OpenClawProtocol/ GatewayModels.swift mirror the new field as `adaptermeta: [String: AnyCodable]?` in the four codegen sites (declaration, init signature, init body, CodingKeys = "adapterMeta"), matching the pattern used for `inputprovenance` and the existing `paperclip` mirror. CHANGELOG.md gets a `Gateway/protocol:` entry under `## Unreleased` describing the namespace + alias and citing openclaw#74635 and openclaw#62102 as the issues being closed. Refs openclaw#74974, openclaw#74635, openclaw#62102
|
Pushed two commits addressing the review feedback.
Two things I'd love a second pair of eyes on before merge — pinging @steipete and @vincentkoc since you've both been on this surface recently:
For the previous head's two red checks: the parity gate failed on |
6f633f3 to
63770c9
Compare
|
Quick rebase + redesign on top of latest I went back through #74635, #62102, and the three earlier PRs that proposed a vendor-named root field (#69139, #72565, #75901, all closed without merge), and I think the maintainers' objection there was the precedent of carving a Paperclip-shaped hole in
Diff against The new I could not run the full Happy to split the alias removal off into a follow-up PR once Paperclip cuts a release that nests under |
|
This pull request has been automatically marked as stale due to inactivity. |
|
This pull request has been automatically marked as stale due to inactivity. |
|
ClawSweeper applied the proposed close for this PR.
|
Summary
Closes #74635, #62102. Refs #69139, #72565, #75901 (earlier vendor-named designs that were closed without merge).
Paperclip and other external agents inject a root-level metadata blob when invoking agents through the
openclaw_gatewayadapter, butAgentParamsSchemais declared withadditionalProperties: false, so the gateway rejects the entire payload before dispatch:Three earlier PRs (#69139, #72565, #75901) tried to land this as a vendor-named root field and were closed without merge. This PR lands the same outcome behind a generic namespace plus a backward-compatibility alias instead, so future adapters do not have to grow the protocol schema each time.
Schema change (
src/gateway/protocol/schema/agent.ts)AgentParamsSchemagains two optional fields, both treated as opaque by the gateway:adapterMeta: Type.Optional(Type.Record(Type.String(), Type.Unknown()))- generic landing pad for opaque per-adapter metadata. Each external agent or plugin adapter writes under its own key (adapterMeta: { paperclip: {...}, greptile: {...} }); the gateway accepts the bag as-is and never inspects it. New adapters land protocol-side without growing the schema.paperclip: Type.Optional(Type.Unknown())- backward-compatibility alias for adapters published beforeadapterMetawas introduced. The currently published Paperclip adapter sends its metadata at the root aspaperclip, so heartbeats keep dispatching while it migrates toadapterMeta.paperclip. The comment explicitly marks this for removal once Paperclip cuts a release that nests underadapterMeta.additionalProperties: falseonAgentParamsSchemais intentionally untouched. Truly unknown root fields (typo'didempotnecyKey,somethingElse, etc.) still fail validation before dispatch.Swift bindings (
apps/shared/OpenClawKit/Sources/OpenClawProtocol/GatewayModels.swift)Mirrors the two new fields on
AgentParamsin all four codegen positions (declaration, init signature, init body,CodingKeys), following the existinginputprovenance/cleanupbundlemcponrunendpattern:public let adaptermeta: [String: AnyCodable]?public let paperclip: AnyCodable?The macOS-side mirror was deleted upstream so only the shared one needs to be regenerated.
Tests (
src/gateway/protocol/agent-params-validator.test.ts, new)New unit-test file covering both the new fields and the unchanged guard:
message/idempotencyKeyrejectedpaperclipalias accepts object, string, number, boolean, nulladapterMetawith one or more adapter keys acceptedadapterMetaandadapterMetawith primitive entry values acceptedpaperclip+adapterMeta.paperclip) acceptedadapterMetawith non-object value rejected (string, number, boolean, null, array)additionalPropertiesguard intact)Changelog
One bullet under
## Unreleased->### Changesdescribing the namespace + alias and citing #74635 and #62102.Local verification
pnpm exec oxfmt --check --threads=1on the touched .ts files: clean.tsxreproducer importing the same TypeBox schema body and compiling it with the same Ajv config assrc/gateway/protocol/index.ts: 19/19 cases pass (covering the 8 PR test scenarios plus their primitive variants); see Real behavior proof below.pnpm test src/gateway/protocol/agent-params-validator.test.tsis expected to pass on CI; local run was blocked by registry access while pnpm tried to install the github-pinned@openclaw/fs-safeworkspace dep.Real behavior proof
Behavior or issue addressed: The gateway rejected agent invocations with a root-level
paperclipmetadata blob (the shape Paperclip rev3494e84actually sends against OpenClaw2026.4.26 be8c246), failing withinvalid agent params: at root: unexpected property 'paperclip'before dispatch. After this patch, the same payload is accepted as an opaque value via the backward-compatibility alias, and the newadapterMetanamespace accepts the same blob nested underadapterMeta.paperclipfor the migration path. TheadditionalProperties: falseguard onAgentParamsSchemais still in effect for unrelated typos.Real environment tested: Local OpenClaw checkout of
jeffrey701/fix/agent-params-accept-paperclip-metadata-74635rebased ontoupstream/mainatf9e8e83a16(currentmaintip); Node.jsv22.22.0; pnpm-resolved[email protected]; OpenClaw workspacetypeboxandajvdependencies as pinned inpackage.json. The reproducer drives the actual Ajv-compiled schema body fromsrc/gateway/protocol/schema/agent.tsagainst the same Ajv configurationsrc/gateway/protocol/index.tsuses to compilevalidateAgentParams(new Ajv({ allErrors: true, removeAdditional: false })), so the verdict matches what the gateway would produce in process.Exact steps or command run after this patch: After applying the schema, Swift binding, test, and changelog edits and committing as
63770c9d4a, from the repo root:The
.validator-repro-74974.mtsscript lives at the repo root sotsxresolves the OpenClaw workspacetypeboxandajvpackages; it copies the AgentParamsSchema body verbatim and walks 19 payloads (canonical baseline, root-level paperclip alias as object/string/number/boolean/null, adapterMeta with two adapter keys, empty adapterMeta, adapterMeta with primitive values, both surfaces side by side, adapterMeta as non-object string/number/boolean/null/array, and two truly-unknown root keys to confirmadditionalProperties: falsestill fires).Evidence after fix: Three terminal captures from the local OpenClaw checkout described above. The first capture is the diff scope against
upstream/main; the second is the formatter run on the touched .ts files; the third is the standalone Ajv-compiled schema reproducer driving 19 payloads throughvalidateAgentParams-shaped validation. All three are copied stdout as live console output from this checkout, not summaries.Scenario A - terminal capture, diff scope vs upstream/main:
Scenario B - terminal capture, formatter check:
Scenario C - terminal capture, Ajv-compiled schema reproducer driving 19 payloads:
Observed result after fix: Live stdout from the three terminal captures above, copied from a real OpenClaw checkout running on Node.js v22.22.0. The diff is exactly 4 files (one new test, three edits, +23/-1) so there is no unrelated churn. The formatter reports the touched .ts files are correctly formatted. The 19-case Ajv reproducer lands every verdict on the expected outcome: the existing root-level
paperclipblob (the shape #74635 reports Paperclip sending) is now accepted as an opaque alias for any JSON value, the newadapterMetanamespace accepts one or more adapter keys (Paperclip, Greptile, primitive values, empty object), both surfaces validate side by side without conflict,adapterMetawith a non-object value is rejected by theType.Record(Type.String(), Type.Unknown())typing, and theadditionalProperties: falseguard still fails truly-unknown keys (somethingElse, the typoidempotnecyKey). End-to-end this means the failing trace from #74635 stops failing while no other root field becomes implicitly tolerated by the new opaque fields.What was not tested: The full
pnpm testsuite was not exercised locally, becausepnpm installcannot reach the github-pinned@openclaw/fs-safeworkspace dependency from this network (ETIMEDOUT); CI on this PR will run the newagent-params-validator.test.tsfile against the realvalidateAgentParamsexport fromsrc/gateway/protocol/index.ts. Live Paperclip end-to-end dispatch (rev3494e84+ OpenClaw2026.4.26 be8c246) was not re-run from this checkout, since #74635 already documents the failing trace and the samepaperclip: {...}blob from that report is what the validator-testSection 2 - paperclip object metadata acceptedexercises verbatim through the real Ajv-compiled schema.