Skip to content

feat(sdk): deliver the approval manifest to the live approval card - #5761

Merged
mmabrouk merged 11 commits into
release/v0.110.0from
agent-config-editing-s3b-wire-py
Aug 7, 2026
Merged

feat(sdk): deliver the approval manifest to the live approval card#5761
mmabrouk merged 11 commits into
release/v0.110.0from
agent-config-editing-s3b-wire-py

Conversation

@mmabrouk

@mmabrouk mmabrouk commented Aug 5, 2026

Copy link
Copy Markdown
Member

Context

When an agent commits content it imported from its workspace, the approval card must show what it is approving: which files were read, and a diff for a field replaced from one. The runner builds that manifest at the permission gate. It reached the frontend only on a cold replay, so on the live path the card had nothing to render and a human approved bytes they never saw.

This lane wires the SDK side of that delivery, plus the catalog changes the read-then-edit loop needs.

Targets agent-config-editing-s3b-wire-runner and is part of the agent-config-editing stack. Read the stack bottom up.

Changes

The manifest gets its own stream part. The Vercel stream adapter emits data-approval-manifest beside the approval request:

{"type": "data-approval-manifest",
 "id": "<toolCallId>",
 "data": {"toolCallId": "...", "approvalId": "...", "manifest": {...}}}

It cannot ride tool-approval-request, which is a strict object with an exact key set pinned by the conformance test. It must not ride the tool's input either, because input is the model's own arguments and the manifest is runner-derived. Putting it there would show the human a payload the model never wrote, which is exactly the confusion the card exists to prevent. The AI SDK passes a data-* part through untouched, so a separate part is the honest place for it.

base_revision_id is now required with the flag on. This is the one change here with a compatibility edge, so read it before approving. With ordered operations enabled, the commit schema lists base_revision_id among its required properties:

Flag off:  required: ["workflow_variant_id", "delta"]
Flag on:   required: ["workflow_variant_id", "base_revision_id", "delta"]

The server already refuses an ordered delta that omits it. Saying so only in prose meant a model sent the call anyway and spent a turn on the refusal, so the schema now states it. workflow_variant_id is bound from run context and stripped from the list along with the property, so the model never sees it as required. Any caller that builds an ordered commit without a base revision was already being refused; it now fails schema validation instead, and earlier.

read_config joins the build kit. A playground agent could commit but never read what it was editing. The op is added to the default build kit when the catalog defines it, which is when ordered operations are on, so the kit carries both halves of the loop or neither.

The commit op points at the scoped route. commit_revision now targets /api/workflows/revisions/commit/agent, in both flag states. That route confines every write to parameters.agent. The path comes from this catalog and the sandbox holds no credential, so this line is where the agent's write scope is decided.

The per-call description is accepted in a second position. A model that puts its note inside the payload object rather than at the top level no longer loses it. Both positions carry x-ag-ephemeral: true, which is what lets the runner lift the field and drop it before the commit without hard-coding a tool name. The marker is the contract: once a nested description is advertised as tolerated, the field name alone can no longer tell the endpoint's own field from a misplaced note, so the decision has to be machine-readable.

The truthy set is a deliberate mirror. _ordered_operations_enabled parses the flag with its own copy of the API's truthy values, because the SDK cannot import from the API. A copy that drifts would turn the ordered arm on in the API while this catalog kept advertising the legacy surface. api/oss/tests/pytest/unit/workflows/test_ordered_operations_flag.py pins the two sets equal; it lives on the API side because that is the one side that can import both.

The flag-off tool description stops contradicting the server. It told the model to send the complete tools list including its own build-kit tools, or lose them. The server now refuses a commit that carries a platform-kind tool entry, so following that instruction earned a rejection on the first commit. The text now says to leave commit_revision, test_run, and read_config out of the list, and states that a commit carrying one is refused.

Documentation follows the protocol. Three design documents described the older shapes: the protocol reference, the tools reference, and the in-service tool resolution interface. They now match what this catalog emits, so the next reader is not working from a contract the code stopped honoring.

Tests

  • test_vercel_stream_approval_manifest.py, 4 tests: the part is emitted when a manifest is present, it is absent when there is none, and the approval request itself is unchanged.
  • test_build_kit_overlay.py pins both build-kit shapes, one per flag state, with each op list written out in full. The flag is read directly rather than through the catalog, so the test states the flag-to-list mapping instead of restating the code it checks.
  • test_ordered_operations_flag.py is the cross-side guard on the truthy mirror. It sits under the API tests rather than the SDK ones, since only that side can import both definitions.
  • test_op_catalog.py pins the scoped commit path, and test_op_catalog_description.py covers both description positions and the required-field split per flag state.
  • The manifest adapter test plus the whole SDK platform suite pass at 168 tests, and the API build-kit and ordered-operations-flag suites at 40, in both flag states. The wider SDK agents suite is green at 807.
  • The frontend half of the card lands in the web lane above this one.

What to QA

  • Ask an agent to import a file from .agenta-imports/ into a skill and commit. The approval card shows the file list and the diff before you approve, without a page reload.
  • Ask it to commit with a short note about the change. The note appears with the request and is absent from the stored revision.
  • Regression: approve a commit that imports nothing. The card still renders and the approval still works.
  • Regression with ordered operations OFF: a commit still succeeds without a base revision id, since the requirement is scoped to the flag-on arm.

@vercel

vercel Bot commented Aug 5, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
agenta-documentation Ready Ready Preview Aug 6, 2026 8:09pm

Request Review

@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 53717d40-5b92-4c61-b0f7-6a44724a653b

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

manifest = payload.get("manifest")
if manifest is not None:
yield {
"type": "data-approval-manifest",

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

The manifest travels in its own data part.

It cannot travel in tool-approval-request. That chunk is a strict object with an exact key set, and the conformance test pins that set.

It must also stay out of input. input holds the arguments of the model, and the runner builds the manifest. A manifest inside input shows the human a payload that the model never wrote.

# operations are enabled, so membership is tested against the catalog itself rather than
# re-reading the flag: an op name the catalog does not define raises `UnknownPlatformOpError`
# for every build-kit resolution.
_READ_CONFIG_OPS: tuple[str, ...] = (

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This line tests the catalog for the op. It does not read the flag.

The catalog defines read_config only when ordered operations are on. An op name that the catalog does not define raises UnknownPlatformOpError for every build-kit resolution.

The catalog test therefore prevents a broken build kit in a deployment that has the flag off.

# every write to `parameters.agent`, and it is the ONLY commit surface the
# agent is given: the path comes from this catalog, and the sandbox holds no
# credential, so an unscoped agent commit cannot be expressed.
path="/api/workflows/revisions/commit/agent",

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This path decides the write scope of the agent. The route confines every write to parameters.agent.

The agent cannot select a different path. This catalog is on the server, and the sandbox holds no credential.

If you change this path back to /api/workflows/revisions/commit, the agent can write harness.permissions and sandbox.kind.

"entries plus your change), or you wipe the rest, including your own build-kit tools. "
"are replaced wholesale, not merged entry-by-entry: send the complete list, meaning "
"your current entries plus your change, or you wipe the rest. Leave the playground's "
"own tools (commit_revision, test_run, read_config) OUT of that list: they are not "

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

The server refuses a commit that contains a tool entry of the platform kind.

The earlier text told the model to send the complete tools list together with its own build-kit tools. A model that obeyed that text received a refusal on its first commit.

This text now names the three tools to omit, and it states the refusal.

@mmabrouk

mmabrouk commented Aug 5, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@mmabrouk
mmabrouk force-pushed the agent-config-editing-s3b-wire-py branch from 4cc3fb3 to 7f77f92 Compare August 5, 2026 20:31
@mmabrouk
mmabrouk force-pushed the agent-config-editing-s3b-wire-runner branch from 477c1ac to a9af42e Compare August 5, 2026 21:25
@mmabrouk
mmabrouk force-pushed the agent-config-editing-s3b-wire-py branch from 7f77f92 to e80845e Compare August 5, 2026 21:25
@mmabrouk
mmabrouk force-pushed the agent-config-editing-s3b-wire-runner branch from a9af42e to c4d1a0f Compare August 5, 2026 21:54
@mmabrouk
mmabrouk force-pushed the agent-config-editing-s3b-wire-py branch from e80845e to 8d275fd Compare August 5, 2026 21:54
@mmabrouk

mmabrouk commented Aug 5, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@mmabrouk
mmabrouk force-pushed the agent-config-editing-s3b-wire-runner branch from 82b5862 to 23ce91f Compare August 6, 2026 15:08
@mmabrouk
mmabrouk force-pushed the agent-config-editing-s3b-wire-py branch from 28316b4 to 395f4ea Compare August 6, 2026 15:09
@mmabrouk
mmabrouk force-pushed the agent-config-editing-s3b-wire-runner branch from 23ce91f to 4ef3731 Compare August 6, 2026 15:18
@mmabrouk
mmabrouk force-pushed the agent-config-editing-s3b-wire-py branch from 395f4ea to 2be2849 Compare August 6, 2026 15:19
@mmabrouk
mmabrouk force-pushed the agent-config-editing-s3b-wire-runner branch from 4ef3731 to b6f7f66 Compare August 6, 2026 15:25
@mmabrouk
mmabrouk force-pushed the agent-config-editing-s3b-wire-py branch from 2be2849 to 6a9d9d7 Compare August 6, 2026 15:26
@mmabrouk
mmabrouk force-pushed the agent-config-editing-s3b-wire-runner branch from b6f7f66 to 609644c Compare August 6, 2026 15:48
@mmabrouk
mmabrouk force-pushed the agent-config-editing-s3b-wire-py branch from 6a9d9d7 to aa02582 Compare August 6, 2026 15:49
@mmabrouk
mmabrouk force-pushed the agent-config-editing-s3b-wire-py branch from aa02582 to 4834ef8 Compare August 6, 2026 15:56
@mmabrouk
mmabrouk force-pushed the agent-config-editing-s3b-wire-runner branch from b52fda2 to 4e469c9 Compare August 6, 2026 16:04
@mmabrouk
mmabrouk force-pushed the agent-config-editing-s3b-wire-py branch from 4834ef8 to a229172 Compare August 6, 2026 16:05

@mmabrouk mmabrouk left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

lgtm

mmabrouk added 11 commits August 6, 2026 22:03
…uild kit

The egress emits a sibling data-approval-manifest part before the strict
approval chunk (which keeps exactly type/approvalId/toolCallId), so the
live card and the replayed card share one payload shape. The catalog
description stops naming a nonexistent revision_id field. read_config
joins DEFAULT_BUILD_KIT_OPS gated on catalog membership, not on a
re-read of the flag, so the kit cannot drift from the catalog.
…ion excludes build-kit tools (final review E2, F10)
…ance in descriptions and skill (E2E U3-U4 root, U7)
…e_revision_id required when ordered (items B and tolerance)
…talog half it pins; below this lane it fails in isolation because the SDK alignment does not exist yet (CI red on every intermediate PR)
… path it expects (instance seven of tests-below-their-code: it landed on s2 while /commit/agent enters the catalog only here, reddening four intermediate PRs)
…ped-route assertion now exists only where the route does
@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Railway Preview Environment

Preview URL https://gateway-pr-5761.up.railway.app/w
Project agenta-oss-clone-spike
Image tag pr-5761-3ea9909
Status Deployed
Railway logs Open logs
Workflow logs View workflow run
Updated at 2026-08-07T09:51:37.799Z

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Backend Feature Request New feature or request Frontend lgtm This PR has been approved by a maintainer size:L This PR changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant