feat(api,frontend): build kit served as the __ag__build_kit static workflow - #5130
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
📝 WalkthroughWalkthroughIntroduces a reserved "build kit" static workflow with a dedicated core overlay builder, blocks embedding of non-embeddable static workflows in resolution/commit paths via a new exception and service checks, and adds frontend logic to fetch and consume the build-kit overlay atom with fallback to per-application context. ChangesBackend: build kit overlay and embed protection
Frontend: agent build-kit overlay consumption
Estimated code review effort: 4 (Complex) | ~60 minutes Sequence Diagram(s)sequenceDiagram
participant Client as Frontend Atom
participant API as fetchAgentBuildKitOverlay
participant WorkflowsService
participant StaticCatalog
Client->>API: fetchAgentBuildKitOverlay(projectId)
API->>WorkflowsService: retrieveWorkflowRevision(BUILD_KIT_WORKFLOW_SLUG)
WorkflowsService->>StaticCatalog: retrieve_revision(slug)
StaticCatalog-->>WorkflowsService: build_agent_template_overlay() data
WorkflowsService-->>API: revision.data.parameters.agent
API-->>Client: validated AgentBuildKitOverlay or null
Client->>Client: fallback to additional_context.playground_build_kit if null/error
sequenceDiagram
participant Caller as create/commit_workflow_revision
participant Service as WorkflowsService
participant Catalog as StaticWorkflowCatalog
participant Resolver as EmbedResolver
Caller->>Service: submit revision data with embeds
Service->>Service: _reject_non_embeddable_workflow_embeds(data)
Service->>Catalog: is_embeddable(id, slug)
Catalog-->>Service: embeddable=False for build-kit slug
Service->>Service: raise NonEmbeddableWorkflowReferenceError
Resolver->>Catalog: is_embeddable(entity.id, entity.slug)
Catalog-->>Resolver: embeddable status
Resolver-->>Caller: reject or return resolved embed
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
api/oss/src/core/workflows/static_catalog.py (1)
246-258: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winCallable revisions bypass the "fail fast" validation guarantee.
The docstring states this method should "Fail fast at construction if any entry is malformed," but callables (line 248-249) are now skipped entirely — no check that the eventual
WorkflowRevisionhasdata.uri, etc. A malformed lazy factory would only surface at firstretrieve_revision()call, not at catalogue construction.Consider invoking each callable once during validation (and catching/re-raising with a clear error) to preserve the fail-fast contract for future callable-based entries.
♻️ Proposed fix to validate callables eagerly
for version, revision in versions.items(): - if callable(revision): - continue + if callable(revision): + revision = revision() if ( not isinstance(revision, WorkflowRevision) or not revision.data or not revision.data.uri ): raise ValueError( f"Static workflow {slug!r} version {version!r} must be a " f"WorkflowRevision with data.uri." )api/oss/tests/pytest/unit/workflows/test_static_catalog.py (1)
392-478: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winAdd coverage for
create_workflow_revisionrejection.Only
resolve_workflow_revisionandcommit_workflow_revisionare tested for build-kit embed rejection, but the PR states rejection is also enforced increate_workflow_revision. Consider adding a parallel test there to lock in that path too.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 3bf988c7-8eb1-430b-ac1f-4fe96b1d15ef
📒 Files selected for processing (17)
api/oss/src/apis/fastapi/applications/overlay.pyapi/oss/src/apis/fastapi/workflows/exceptions.pyapi/oss/src/apis/fastapi/workflows/router.pyapi/oss/src/core/embeds/exceptions.pyapi/oss/src/core/embeds/utils.pyapi/oss/src/core/workflows/build_kit.pyapi/oss/src/core/workflows/interfaces.pyapi/oss/src/core/workflows/service.pyapi/oss/src/core/workflows/static_catalog.pyapi/oss/tests/pytest/unit/applications/test_build_kit_overlay.pyapi/oss/tests/pytest/unit/workflows/test_static_catalog.pydocs/design/agent-workflows/documentation/tools.mdweb/packages/agenta-entities/src/workflow/api/api.tsweb/packages/agenta-entities/src/workflow/api/index.tsweb/packages/agenta-entities/src/workflow/state/store.tsweb/packages/agenta-entities/tests/unit/agent-build-kit-overlay-api.test.tsweb/packages/agenta-entities/tests/unit/agent-build-kit-overlay-atom.test.ts
| def _reject_non_embeddable_static_workflow(entity: Any) -> None: | ||
| catalog = getattr(workflows_service, "static_catalog", None) | ||
| if not catalog or not entity: | ||
| return | ||
| slug = getattr(entity, "slug", None) or getattr( | ||
| entity, "workflow_slug", None | ||
| ) | ||
| entity_id = getattr(entity, "id", None) | ||
| if not catalog.is_embeddable(id=entity_id, slug=slug): | ||
| raise NonEmbeddableWorkflowReferenceError(slug or str(entity_id)) | ||
|
|
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Find all call sites of create_universal_resolver and check whether workflows_service always carries a static_catalog
rg -n 'create_universal_resolver\(' -A 10 -B 5 --type=py
rg -n 'WorkflowsService\(' -A 10 --type=pyRepository: Agenta-AI/agenta
Length of output: 154
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Locate relevant files and call sites.
git ls-files | rg 'api/oss/src/core/(embeds/utils\.py|workflows|.*resolver.*|.*service.*)\.py$|api/oss/src/core/.+\.py$' || true
echo '--- create_universal_resolver call sites ---'
rg -n 'create_universal_resolver\(' api/oss/src -g '*.py' -A 6 -B 6 || true
echo '--- WorkflowsService definitions/usages ---'
rg -n 'class WorkflowsService|WorkflowsService\(' api/oss/src -g '*.py' -A 8 -B 8 || true
echo '--- static_catalog references ---'
rg -n 'static_catalog' api/oss/src -g '*.py' -A 4 -B 4 || true
echo '--- embed helper context ---'
sed -n '250,310p' api/oss/src/core/embeds/utils.pyRepository: Agenta-AI/agenta
Length of output: 25624
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo '--- relevant files ---'
git ls-files api/oss/src/core | rg 'embeds/utils\.py|workflows|resolver|service' || true
echo '--- create_universal_resolver call sites ---'
rg -n 'create_universal_resolver\(' api/oss/src -g '*.py' -A 6 -B 6 || true
echo '--- WorkflowsService definitions/usages ---'
rg -n 'class WorkflowsService|WorkflowsService\(' api/oss/src -g '*.py' -A 8 -B 8 || true
echo '--- static_catalog references ---'
rg -n 'static_catalog' api/oss/src -g '*.py' -A 4 -B 4 || true
echo '--- embed helper context ---'
sed -n '270,300p' api/oss/src/core/embeds/utils.pyRepository: Agenta-AI/agenta
Length of output: 16731
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo '--- helper call sites in embeds/utils.py ---'
rg -n '_reject_non_embeddable_static_workflow\(' api/oss/src/core/embeds/utils.py -A 4 -B 4 || true
echo '--- workflow non-embeddable slug guard context ---'
sed -n '1320,1365p' api/oss/src/core/workflows/service.py
echo '--- resolver workflow branch context ---'
sed -n '288,430p' api/oss/src/core/embeds/utils.pyRepository: Agenta-AI/agenta
Length of output: 10176
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo '--- embeds service wiring ---'
sed -n '1,140p' api/oss/src/core/embeds/service.py
echo '--- all WorkflowsService instantiations with context ---'
rg -n 'WorkflowsService\(' api/oss/src -g '*.py' -A 4 -B 4 || true
echo '--- static_catalog provider wiring ---'
rg -n 'StaticWorkflowProvider|static_catalog=' api/oss/src -g '*.py' -A 4 -B 4 || trueRepository: Agenta-AI/agenta
Length of output: 11016
Resolver should short-circuit reserved build-kit slugs even without a catalog.
_reject_non_embeddable_static_workflow returns early when workflows_service.static_catalog is unset, and the default WorkflowsService wiring leaves that field unset. That lets the embed resolver accept build-kit and other reserved static workflows. Add the BUILD_KIT_WORKFLOW_SLUG fallback before the catalog check.
Context
Agents created through the template-builder and playground-native flows showed no build kit in Advanced and ran without its tools, even after committing. The kit was delivered solely as a rider on
GET /simple/applications/{id}, keyed by aworkflow_idthat ephemeral drafts don't have. Design (reviewed by codex at xhigh, then implemented per the folded plan): the kit becomes the reserved static workflow__ag__build_kit— a constant agent configuration in the StaticWorkflowCatalog, same namespace as the other__ag__*platform constants. Stacked on the design-docs PR #5124.Changes
Backend:
core/workflows/build_kit.py(new): the kit's content builder — forced builtins, the 13DEFAULT_BUILD_KIT_OPS, the request-connection tool embed, the build-an-agent skill embed, sandbox permissions. Core owns the content;apis/fastapi/applications/overlay.pyshrinks to a thin back-compat adapter (core never imports the API layer).static_catalog.py: the__ag__build_kitentry with explicit per-entry metadata (kind,embeddable) on every catalog entry, lazy revision factories, and anis_embeddableaccessor. The old "non-skill means tool" inference is gone; onlyrequest_connectionis a tool embed, so the kit cannot embed itself.__ag__build_kitis retrievable but not embeddable/committable — enforced with a typed error at the embed resolver AND the commit path (commits don't resolve embeds, so resolver-only enforcement wouldn't hold).Frontend:
agentBuildKitOverlayAtom: fetches the kit once per project by resolving the slug through the existing workflow-retrieve path;staleTime: Infinity.workflowAgentTemplateOverlayAtomFamily: gates on the target entity being agent-typed (flags on committed revisions, flags on ephemerallocal-*drafts, builtin-URI fallback) and serves the slug-fetched kit; the legacy per-application chain is retained as a deployment-skew fallback (used only when the slug fetch definitively fails and aworkflow_idexists).fetchSimpleApplication(used but never imported since merge9cb1586329) — the fallback needs it to compile.Scope / risk
The per-application
additional_contextrider is untouched this release (retirement is the planned follow-up once the FE migration has soaked).useBuildKitand the rendering are unchanged — only the data source moved. The kit content is byte-equivalent to the old overlay output (pinned by test). Risk to watch: any consumer that enumerated non-skill catalog entries as tools now needs the explicit allowlist (all in-repo consumers updated; the tests would catch a regression).Tests / verification
@agenta/entities: 11 new tests (slug fetch shape, boundary validation, ephemeral/committed/non-agent gating, no-session, fallback on error and on null); lint, types, build green. Two pre-existing failing test files (retrieveWorkflowRevision.test.ts,trace-migration-api.test.ts, real-HTTP tests) unrelated and unchanged.__ag__build_kitreturns the typed 400.__ag__build_kitretrieve (proving the new path, not the fallback).How to QA
Prerequisites: any dev stack on this branch (api restart needed if the container predates the change — the bind-mount reload misses new modules).
Steps:
POST /api/workflows/revisions/retrievewith{"workflow_ref": {"slug": "__ag__build_kit"}}→ the kit revision.__ag__build_kit→ 400 "retrievable but cannot be embedded".Automated tests:
cd api && uv run --no-sync python -m pytest oss/tests/pytest/unit/applications/ oss/tests/pytest/unit/workflows/ -qandcd web && pnpm --filter @agenta/entities test.Edge cases: a non-agent workflow (prompt/evaluator) must show no kit; an old cached frontend keeps working via the untouched rider.
https://claude.ai/code/session_01N2djTMgXnpk84EqtugHDJB