Skip to content

feat(agents): config-driven local-model backend for CE copilots#365

Merged
sudoshi merged 2 commits into
mainfrom
feature/local-model-agent-backend-ce
Jun 16, 2026
Merged

feat(agents): config-driven local-model backend for CE copilots#365
sudoshi merged 2 commits into
mainfrom
feature/local-model-agent-backend-ce

Conversation

@sudoshi

@sudoshi sudoshi commented Jun 16, 2026

Copy link
Copy Markdown
Collaborator

Why

The Studies/Publish/Abby copilots run on the Claude Agent SDK in python-ai (ai/app/agents/service.py), which drives the claude CLI against the Anthropic cloud API. Nothing gated them by edition — they were "EE-only" purely because the CLI needs a funded ANTHROPIC_API_KEY. CE deployments need the same omnipresent Abby without a cloud dependency.

The agent loop (9-tool in-process MCP server, can_use_tool approval gating, Reverb streaming, HIGHSEC lockdown) is model-agnostic — it lives in our code, not Anthropic's. So CE support is a runtime config decision, not a code fork: change only where the CLI sends requests and which tools are auto-enabled.

What changed

  • config (ai/app/config.py): AGENT_PROVIDER + AGENT_LOCAL_* settings and resolve_agent_provider()ResolvedAgentProvider.
  • service (_options()): for the local provider, swap in the local model/effort and inject ANTHROPIC_BASE_URL/ANTHROPIC_AUTH_TOKEN via ClaudeAgentOptions.env (redirects the CLI subprocess to a proxy — no change to tool/approval/streaming logic); withdraw approval-gated WRITE tools when local actions are disabled.
  • profiles: optional per-profile provider override (inherits the global).
  • router + AbbyAgentController: surface provider + actions_enabled so the dock hides action affordances on a reads-only CE deployment.
  • frontend: store the flags; AbbyCopilotPanel shows a reads-only note when actions are disabled.
  • docker: claude-code-router sidecar gated behind profiles: ["ce"] (inert in the EE stack), non-root per HIGHSEC 4.1.

EE / CE matrix

EE (anthropic) CE (local, actions off) CE (local, actions on)
Model Opus 4.7/4.8 Qwen2.5-Coder-32B (local) same
Omnipresent dock + reads
Gated write actions ❌ (hidden) ✅ (model-dependent)
External API cost yes $0 $0

Defaults preserve EE behavior end-to-end (anthropic provider, Opus, actions on). The first service test asserts the cloud model + gated writes when the provider defaults to anthropic.

Verification

Verified with the SDK client mocked (no GPU/credit): Python 41, PHP 5, frontend 9; mypy/Pint/PHPStan/tsc/vite build clean; docker compose config valid with the sidecar correctly inert outside --profile ce. Deployed to prod — EE path unchanged (/health 200, resolver reports anthropic/claude-opus-4-7).

NOT verified here (operator action)

The claude-router image build + live boot + a real local-model turn need a host with Ollama and AGENT_LOCAL_MODEL pulled (+ GPU). Operator smoke steps are in docs/lineage/modules/abby-ai/local-model-agent-backend-ce.md.

🤖 Generated with claude-flow

sudoshi and others added 2 commits June 15, 2026 21:09
The Studies/Publish/Abby copilots run on the Claude Agent SDK and were
"EE-only" purely because the claude CLI needs a funded Anthropic key. The
agent loop (MCP tools, can_use_tool approval gating, Reverb streaming,
HIGHSEC lockdown) is model-agnostic, so CE support is a runtime config
decision, not a code fork.

- config: AGENT_PROVIDER + AGENT_LOCAL_* settings and resolve_agent_provider()
- service._options(): for the local provider, swap in the local model/effort
  and inject ANTHROPIC_BASE_URL/ANTHROPIC_AUTH_TOKEN via ClaudeAgentOptions.env
  (redirects the CLI to a proxy, no change to tool/approval/streaming logic);
  withdraw approval-gated WRITE tools when local actions are disabled
- profiles: optional per-profile provider override (inherits global)
- router + AbbyAgentController: surface provider + actions_enabled so the dock
  hides action affordances on a reads-only CE deployment
- frontend: store the flags; AbbyCopilotPanel shows a reads-only note
- docker: claude-code-router sidecar gated behind profiles:["ce"] (inert in the
  EE stack), non-root per HIGHSEC 4.1

Defaults preserve EE behavior end-to-end (anthropic provider, Opus, actions on).
Verified with the SDK client mocked (no GPU/credit): Python 41, PHP 5,
frontend 9; mypy/Pint/PHPStan/tsc/vite build clean; compose valid with the
sidecar correctly inert outside --profile ce. The proxy's live boot needs an
operator box with Ollama + the model pulled (steps in the devlog).

Co-Authored-By: claude-flow <ruv@ruv.net>
Six agent-provider vars for the EE/CE switch, defaults preserving EE behavior.
They already work via docker-compose ${VAR:-default} interpolation; this just
makes them discoverable in the example env.

Co-Authored-By: claude-flow <ruv@ruv.net>
@sudoshi sudoshi merged commit 0bfc7f9 into main Jun 16, 2026
25 of 26 checks passed
@sudoshi sudoshi deleted the feature/local-model-agent-backend-ce branch June 16, 2026 20:23
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.

1 participant