Skip to content

fix(agents): thread adopt_existing_workspace through create_agent_internal facade - #1769

Merged
AndriiPasternak31 merged 1 commit into
devfrom
feature/1768-deploy-local-adopt-kwarg
Jul 26, 2026
Merged

fix(agents): thread adopt_existing_workspace through create_agent_internal facade#1769
AndriiPasternak31 merged 1 commit into
devfrom
feature/1768-deploy-local-adopt-kwarg

Conversation

@vybe

@vybe vybe commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Fixes #1768

Summary

POST /api/agents/deploy-local (and the MCP deploy_local_agent tool) returned 500 on every call: deploy.py passes adopt_existing_workspace=True through create_agent_fn, but the router facade create_agent_internal in routers/agents.py never accepted that kwarg — #1667 added it only to the service-layer crud.py function. The call died with:

TypeError: create_agent_internal() got an unexpected keyword argument 'adopt_existing_workspace'

Change

One facade signature fix in src/backend/routers/agents.py: accept adopt_existing_workspace: bool = False and forward it to the service-layer _create_agent_internal(...) call. Default False preserves every other caller's behavior (all callers checked — leading positionals + keywords only, so a trailing default kwarg is inert for them).

Validation (live dev stack)

  • Red baseline reproduced before the fix: the exact TypeError above returned as a 500 by the running backend.
  • All 7 failing tests from the issue pass after the fix: test_deploy_local.pyTestDeployLocalSuccessful (×4), TestDeployLocalResponse::test_response_structure, TestDeployLocalVersioning::test_redeploy_creates_version — plus test_agent_quota.py::TestAgentQuotaRedeploy::test_redeploy_existing_agent_bypasses_quota. Real agent containers created/torn down (7 passed in 150s).
  • Full test_deploy_local.py: 16/16 passed (98s) — auth, validation, security, limits classes included.
  • Redeploy/versioning path confirms the bug: agent creation silently reuses a pre-existing Docker volume of the same name (get-then-create, no adopt/refuse decision) #1667 adopt behavior is preserved (pre-populated workspace volume is mounted, not refused).

🤖 Generated with Claude Code

…ernal facade (#1768)

The deploy-local path (#950) passes adopt_existing_workspace=True through
create_agent_fn, but the router facade create_agent_internal never accepted
the kwarg (added to the service layer in #1667), so every
POST /api/agents/deploy-local and MCP deploy_local_agent call died with
"TypeError: unexpected keyword argument 'adopt_existing_workspace'" -> 500.

Add the kwarg (default False) to the facade and forward it to the
service-layer call. All other callers are unaffected.

Validated live against the dev stack: the 7 failing tests from the issue
plus the rest of test_deploy_local.py (16/16) now pass; red baseline
reproduced the exact TypeError before the fix.

Fixes #1768

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vybe
vybe marked this pull request as ready for review July 26, 2026 07:48
@github-actions

Copy link
Copy Markdown

⚠️ Nightly unit-suite check skipped — merge conflict against dev.

Resolve by running git merge dev locally and pushing the result. The next nightly run will re-test once the conflict is gone.

@AndriiPasternak31

Copy link
Copy Markdown
Contributor

PR Validation Report — /validate-pr

PR: #1769 — fix(agents): thread adopt_existing_workspace through create_agent_internal facade
Author: @vybe · Branch: feature/1768-deploy-local-adopt-kwargdev · Files: 1 (+4/−2)
Linked issue: #1768priority-p0, type-bug, theme-infrastructure, complexity-low
CI: ✅ green — 18 checks SUCCESS (pytest × 3 seeds head+base, CodeQL, gitleaks, schema-parity, non-root, prod-image-smoke); 3 skipped are ui-label-gated e2e + dependabot auto-merge.

Summary

Category Status Notes
Commit Messages Single commit 443141db, conventional fix(agents):, states what + why
Base Branch Targets dev
PR Size 1 file, +4/−2 — minimal
Status Auto-Promotion Fixes #1768 same-repo closing keyword → auto-promotes to status-in-dev on merge
Roadmap Issue resolves in abilityai/trinity (both trackers probed); correct priority + type labels
Requirements Bug fix restoring documented behavior — no scope change
Architecture No endpoint, schema, integration or component change
Feature Flows Behavior restored, not changed
Security Check 4.1–4.6 clean — no keys, emails, public IPs, .env, hardcoded secrets, credential files
Infrastructure No compose / Dockerfile / nginx change
Build Packaging (4.8) No new top-level src/backend/*.py
Config Packaging (4.9) No new os.getenv() var
Test Adequacy ⚠️ No named regression test in the diff — see Warnings
Code Quality Focused, no scope drift, matches existing facade pattern
Requirements Trace Maps 1:1 to issue AC #1; ACs #2#5 evidenced by the live-stack run in the PR body

End-to-end trace (verified against origin/dev, not just the diff)

The kwarg chain resolves correctly in both directions:

  1. Originservices/agent_service/deploy.py:611-621 calls create_agent_fn(..., adopt_existing_workspace=True).
  2. Injection pointrouters/agents.py:467 passes create_agent_fn=create_agent_internal — the facade, confirming the deploy path never reaches crud.py directly.
  3. Break (pre-fix) — facade signature at routers/agents.py:103 had no adopt_existing_workspace and no **kwargsTypeError → 500. Matches the stack in bug: deploy-local returns 500 — create_agent_internal facade drops adopt_existing_workspace kwarg #1768.
  4. Consumercrud.py:1729-1736 accepts the kwarg; consumed at crud.py:1790 by _guard_leftover_workspace_volume(...) (crud.py:279-312), which skips the bug: agent creation silently reuses a pre-existing Docker volume of the same name (get-then-create, no adopt/refuse decision) #1667 409-refusal when adopting. The new plumbing does reach the real consumer.
  5. MCP surfacesrc/mcp-server/src/tools/agents.ts:706,779 POSTs to /api/agents/deploy-local, riding the same repaired path. No MCP change needed (Invariant feat: SMARTS trading pipeline with Telegram notifications and Miro visualization #13 — no contract change).

All other facade callers verified unaffected: routers/agents.py:436 (3 positionals + skip_name_sanitization=), services/system_service.py:849 via _default_create_agent_fn (all-keyword), and cornelius_agent_service.py:181 (imports crud.create_agent_internal directly, bypassing the facade). A trailing defaulted kwarg is inert for all three.

Facade/service parity is now complete — the facade covers every crud.create_agent_internal param except ws_manager, which it deliberately injects. This was the last drifted kwarg.

Bug attribution independently confirmed (not taken from the PR body): git log -S"adopt_existing_workspace" pins introduction to f55eb6cb (2026‑07‑17, PR #1666), whose --name-only touches crud.py and deploy.py but not routers/agents.py. The later #1484 decomposition (f6b81ace, PR #1691) never touched the facade either. So deploy-local has 500'd on every call for ~8 days.

Architectural hot-spot check (#1484): the diff touches only the router facade — not crud.create_agent_internal or any fenced phase-helper. No re-monolithing, no helper grew, no if docker_client: fencing disturbed.

Issues found

Critical (block merge) — none.

Warnings (review required)

⚠️ No named regression test. Severity is higher than the 4-line diff suggests, because of why the bug survived CI:

Cheap, permanent guard (~10 lines, matching 7 existing parity-test precedents — test_1560_agent_redis_key_parity.py, test_credential_paths_parity.py, test_model_context_parity.py, test_agent_cleanup_parity.py, …):

# tests/unit/test_1768_create_agent_facade_parity.py
import inspect

def test_facade_accepts_every_service_kwarg():
    from routers.agents import create_agent_internal as facade
    from services.agent_service.crud import create_agent_internal as service
    svc = set(inspect.signature(service).parameters) - {"ws_manager"}  # facade injects this
    assert svc <= set(inspect.signature(facade).parameters)

Judgment: warning, not a blocker. The fix is correct by inspection (full chain traced above), the default is inert for every other caller, and the author documented a red baseline plus 16/16 test_deploy_local.py green on a live stack. Holding a P0 restore of a fully-dead deploy path hostage to a test file is the wrong trade — but the guard should land as an immediate follow-up.

Suggestions (optional)

Recommendation

✅ APPROVE

Correct, genuinely minimal fix for a P0 regression that has had POST /api/agents/deploy-local and the MCP deploy_local_agent tool returning 500 on every call since 2026‑07‑17. Kwarg threaded end-to-end, default inert for all three other callers (each individually verified), #1484 phase-helper structure untouched, all security greps clean, packaging checks N/A, CI green across 18 checks.

Follow-up requested: file the ~10-line facade/service signature-parity test as a type-bug / complexity-low issue referencing #1768 — the drift class that produced this P0 is otherwise still CI-invisible.

🤖 Validated with Claude Code via /validate-pr

@AndriiPasternak31 AndriiPasternak31 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Approved via /validate-pr — see the validation report above. Correct minimal P0 fix; kwarg traced end-to-end (deploy.py → facade → _guard_leftover_workspace_volume), all three other facade callers verified inert, #1484 phase-helper structure untouched, CI green across 18 checks. One non-blocking follow-up requested: the facade/service signature-parity unit test.

@AndriiPasternak31
AndriiPasternak31 merged commit 23b300d into dev Jul 26, 2026
21 checks passed
@AndriiPasternak31
AndriiPasternak31 deleted the feature/1768-deploy-local-adopt-kwarg branch July 26, 2026 09:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants