Skip to content

[#5162] fix(frontend): forward variant references on draft playground runs - #5163

Merged
mmabrouk merged 3 commits into
big-agentsfrom
docs/draft-run-references-plan
Jul 9, 2026
Merged

[#5162] fix(frontend): forward variant references on draft playground runs#5163
mmabrouk merged 3 commits into
big-agentsfrom
docs/draft-run-references-plan

Conversation

@mmabrouk

@mmabrouk mmabrouk commented Jul 8, 2026

Copy link
Copy Markdown
Member

Context

When an agent commits itself in the playground, the first commit_revision works, but every
later commit_revision in the same conversation fails with:

missing run-context value for direct-call binding 'workflow_revision.workflow_variant_id'

The cause is on the frontend. commit_revision is a platform op whose target variant is a
context binding, filled from the run's references block, never by the model. The request
builder gated that whole block on an all-or-nothing rule: if the loaded revision had unsaved
edits (isDirty), it sent references: null. With no references, the run context has no
variant, and the runner throws.

"Dirty" here does not mean the panel lags a newer revision. It means the loaded revision
carries a draft overlay, for any reason: the user edited the config panel, or the panel had
edits before the conversation started, or the post-commit repointing added in #4920 did not
land. Whenever that was true, the old gate dropped the variant and the commit failed.

Changes

The gate is now field-level instead of all-or-nothing. application and application_variant
forward whenever they exist. application_revision forwards only on a clean run, because the
revision reference is the one signal that marks a run as non-draft (is_draft = revision is None in the SDK). An empty result still falls back to null.

The references block on a dirty run of a committed agent:

Before:

"references": null

After:

"references": {
  "application":         {"id": "<app-uuid>",     "slug": "my-agent"},
  "application_variant": {"id": "<variant-uuid>", "slug": "my-agent.default"}
}

The run context now has variant.id set and revision unset, so is_draft stays true and
commit_revision has its target. A clean run is unchanged: it still sends all three families
and stays non-draft.

This lives on the frontend read path because the frontend owns the run identity and knows
exactly which variant is loaded. It is one gate expression in one file, plus tests. No wire,
SDK, or runner change: the backend already reads the variant reference it is handed.

The design docs on this PR carry the full mechanism, the reasoning for the frontend layer, and
the verification that forwarding a bare variant does not re-resolve it to a HEAD revision:
docs/design/agent-workflows/projects/draft-run-references/.

Scope / risk

  • Only the playground reference gate changes. A never-committed local draft still forwards no
    variant, because it has no real variant id yet. That case is unchanged and out of scope.
  • The docs(agent): frontend round-trip design (client tools, commit refresh, connections) #4920 post-commit repointing depends on a stream event arriving. If the stream aborts or
    the event is missed, the panel stays on the old revision and reads as dirty. This fix makes
    the run correct in that case; tightening the repointing is a separate display concern.
  • Deferred follow-up: an integration or replay test for the full self-commit loop (first and
    second commit in one conversation), noted in status.md.

Tests

  • web/packages/agenta-playground/tests/unit/agentRequest.test.ts: dirty committed run
    (references carry app + variant, omit revision), truly-uncommitted local draft (references
    null), a mixed case (local draft revision id under a committed variant still forwards app +
    variant), and an invariant guard (a dirty run still carries data.parameters, so the
    backend hydration gate never fires).
  • 31/31 in the file, 196/196 in the package. pnpm lint-fix clean.

How to QA

Prerequisites: local dev stack, or any environment with an agent app that has been
committed at least once.

Steps:

  1. Open the playground for a committed agent.
  2. In one conversation, ask the agent to make a change and commit it.
  3. Without reloading, ask for a second change and commit it in the same conversation.

Expected result: Both commits land and two new versions appear, with no page reload. The
second commit no longer fails with the workflow_revision.workflow_variant_id binding error.

Automated tests:

pnpm --filter @agenta/playground test -- agentRequest

Edge cases: A clean run (no unsaved edits) must still send all three reference families
and stay non-draft. A brand-new agent that was never committed still cannot self-commit, which
is correct: there is no variant to target yet.

Closes #5162.

https://claude.ai/code/session_01CSTSEXSe4DDhoXCFjZpZ5W

An agent that edits its own config can commit once, then every later commit in
the same conversation fails with 'missing run-context value for direct-call
binding workflow_revision.workflow_variant_id'. Root cause: the playground sends
references: null on a dirty run, dropping the variant identity that commit_revision
needs. Recommends forwarding the variant reference on every run while gating only
the committed-revision reference on !isDirty, so is_draft is preserved.

Refs #5162

Claude-Session: https://claude.ai/code/session_01AumZJ9xRd4XYNHThqy4rTv
@vercel

vercel Bot commented Jul 8, 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, Comment Jul 9, 2026 2:40pm

Request Review

@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Added design notes and guidance for handling draft-run references in agent workflows.
    • Draft runs now keep workflow/app identity available while omitting only revision-specific data when appropriate.
  • Bug Fixes

    • Fixed a self-commit issue where repeated commits in the same chat could fail until refresh.
    • Improved request handling so dirty runs no longer drop all references at once.
  • Tests

    • Updated unit coverage for clean, dirty, and draft commit scenarios.

Walkthrough

This PR documents and fixes a bug where repeated commit_revision calls in the same chat fail after the first commit due to loss of variant identity on "dirty" draft runs. Design docs trace root cause; agentRequest.ts is updated to forward application/application_variant references while gating only application_revision on cleanliness, with unit tests updated accordingly.

Changes

Draft-run references fix and design docs

Layer / File(s) Summary
Bug context and reproduction
docs/design/agent-workflows/projects/draft-run-references/context.md
Documents the observed failure mode, reproduction sessions/error message, impact on the self-edit loop, and design scope/goals/non-goals.
Root cause research
docs/design/agent-workflows/projects/draft-run-references/research.md
Traces the failure from schema stripping through run-context assembly to the playground's all-or-nothing reference gate, with worked examples and hydration/app-scoping verification.
Fix plan and options analysis
docs/design/agent-workflows/projects/draft-run-references/plan.md
Defines invariants, compares frontend field-level gating vs backend variant derivation, recommends the frontend fix, and specifies acceptance checks and test plan.
Frontend reference gating implementation and tests
web/packages/agenta-playground/src/state/execution/agentRequest.ts, web/packages/agenta-playground/tests/unit/agentRequest.test.ts
Changes buildAgentRequest to always forward application/application_variant and gate application_revision on cleanliness; updates unit tests for dirty, clean, and mixed reference scenarios.
Status and verification record
docs/design/agent-workflows/projects/draft-run-references/README.md, docs/design/agent-workflows/projects/draft-run-references/status.md
Adds a top-level README summarizing the fix and reading order, plus a status doc recording approval, implementation, test results, and deferred follow-ups.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

  • Agenta-AI/agenta#4904: Both PRs modify buildAgentRequest in agentRequest.ts and its unit tests to change how references are gated for dirty vs clean runs.
  • Agenta-AI/agenta#4936: Backend/tooling hardening around commit_revision requiring a variant id, directly related to the frontend fix forwarding application_variant.
  • Agenta-AI/agenta#4997: Also modifies the frontend agent message request path feeding buildAgentRequest.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly matches the main fix: forwarding variant references for draft playground runs.
Description check ✅ Passed The description directly explains the bug, the frontend fix, and the test coverage.
Linked Issues check ✅ Passed The changes address #5162 by preserving variant references on dirty runs so repeated self-commits can succeed without reload.
Out of Scope Changes check ✅ Passed The added docs and tests all support the same frontend fix and do not introduce unrelated scope.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 60.00%.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch docs/draft-run-references-plan

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.

1. You load the agent. The panel matches the committed HEAD. `isDirty` is false.
2. You ask for a change. The agent calls `commit_revision`. References are sent in full.
The commit works and creates a **new** revision. The HEAD moves forward.
3. The panel you loaded now lags the new HEAD. The dirty check compares the panel against

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.

I'm not sure I understand how we are determining this is dirty. What does it mean that we compare to HEAD? What is HEAD actually? I'm not sure here. Is it like a bug? I think it is a new bug where, if there is a commit, then we kind of update the page to the new commit. When there is a regression there and the page has not been updated, maybe that's the source of the issue. That's why it's shown as dirty, but it's not supposed to be.

I want to understand exactly what's the logic there, because obviously dirty means the thing that is loaded has been edited, and probably the thing that is loaded is HEAD, so that makes sense. The issue is apparently it has not been really loaded in the UI, so that's why the comparator is not working. That's my guess.

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.

Good catch, and the doc was wrong here, so it is rewritten. isDirty does not compare the panel against a newer HEAD. It compares the loaded revision draft overlay against that same revision own immutable server snapshot (web/packages/agenta-entities/src/workflow/state/store.ts:1897-1934), both keyed by the same revision id. So "dirty" means only that the loaded revision carries a draft overlay. Your suspected stale-page-after-commit problem was real historically and is already handled by #4920: the backend emits a data-committed-revision event and the chat panel calls switchEntity to repoint onto the new revision id, which has no overlay, so isDirty resets. The residual risk is that the event can be missed or the stream aborted, which is one more reason the run must carry the variant on every call. Full detail in research.md, "What dirty means, and why the loop happens".


## The decision in one line

Stop dropping the variant reference on a dirty run. Keep dropping only the revision

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.

If I understand correctly, are we also dropping the application reference, like the workflow reference, and we should not , no?

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.

Yes. Today the code drops all three families together on a dirty run. The fix keeps application and application_variant and drops only application_revision when the run is dirty, because the revision reference is the one signal that marks a run as non-draft. See the gate change in web/packages/agenta-playground/src/state/execution/agentRequest.ts and plan.md Option 1 (the decision line now names the application reference explicitly).

Comment thread docs/design/agent-workflows/projects/draft-run-references/plan.md
@mmabrouk mmabrouk changed the title [#5162] docs(agent-workflows): fix agent self-commit draft-run bug (design) [#5162] fix(frontend): forward variant references on draft playground runs Jul 9, 2026
@mmabrouk
mmabrouk marked this pull request as ready for review July 9, 2026 14:40
@mmabrouk

mmabrouk commented Jul 9, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@dosubot dosubot Bot added the size:XL This PR changes 500-999 lines, ignoring generated files. label Jul 9, 2026
@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

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.

@dosubot dosubot Bot added the Frontend label Jul 9, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
web/packages/agenta-playground/src/state/execution/agentRequest.ts (1)

342-354: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Condense the reference-gate comment to comply with the one-line comment guideline.

The constraint being documented is genuinely surprising (cross-layer draft-ness derivation, bare-variant safety), but 13 lines exceeds what qualifies as a "brief exception." As per coding guidelines, "Keep in-code comments to one short line maximum unless a genuinely surprising constraint requires a brief exception."

♻️ Suggested condensed comment
-    // Field-level reference gate. The service derives draft-ness purely from the revision
-    // reference — `services/oss/src/agent/tracing.py` `_run_context_workflow`:
-    // `is_draft = revision is None` — so ONLY `application_revision` is gated on cleanliness:
-    //  - dirty (unsaved left-panel edits) or an uncommitted local draft (no real revision UUID):
-    //    the run is an inline-config draft, so the revision reference is withheld to keep
-    //    `is_draft` true.
-    // `application` and `application_variant` are forwarded whenever they exist, independent of
-    // dirtiness: the variant identifies WHICH variant is running, which is orthogonal to
-    // draft-ness, and a self-targeting tool (e.g. `commit_revision`) needs that variant to bind
-    // to even on a draft run. Forwarding a bare variant does not resurrect `is_draft`: the
-    // backend only re-resolves a variant reference to its HEAD revision when the request carries
-    // no `data.parameters` (`resolver.py` `needs_reference_hydration`), and a playground run
-    // always sends `data.parameters` — see the "invariant guard" test for this file.
+    // Field-level reference gate: only `application_revision` is gated on cleanliness
+    // (backend: `is_draft = revision is None`). `application`/`application_variant` always
+    // forward — the variant is orthogonal to draft-ness and needed by `commit_revision`.
+    // A bare variant won't resurrect `is_draft`: the backend only re-resolves it when
+    // `data.parameters` is absent, which a playground run never is.

Source: Coding guidelines


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 02e3d82e-8577-49f1-8d8b-3b8c24ab4aed

📥 Commits

Reviewing files that changed from the base of the PR and between 26404f1 and f3e140e.

📒 Files selected for processing (7)
  • docs/design/agent-workflows/projects/draft-run-references/README.md
  • docs/design/agent-workflows/projects/draft-run-references/context.md
  • docs/design/agent-workflows/projects/draft-run-references/plan.md
  • docs/design/agent-workflows/projects/draft-run-references/research.md
  • docs/design/agent-workflows/projects/draft-run-references/status.md
  • web/packages/agenta-playground/src/state/execution/agentRequest.ts
  • web/packages/agenta-playground/tests/unit/agentRequest.test.ts

@mmabrouk
mmabrouk merged commit 0ffc617 into big-agents Jul 9, 2026
18 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Frontend size:XL This PR changes 500-999 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant