Feature/add support for acp agents#284
Conversation
- Introduced a new agent type "acp" that allows delegation to coding CLIs (Claude Code, Codex, Gemini CLI, or custom servers). - Updated the Agent entity to include fields for agent_type, acp_provider, acp_command, and acp_bridge_token_hash. - Modified the agent creation and update processes to handle ACP-specific validations and requirements. - Implemented GenerateACPBridgeToken functionality to issue local-bridge auth tokens for ACP agents. - Added new API endpoints for generating ACP bridge tokens and checking their status. - Created a database migration to add necessary columns and constraints for ACP agents.
… event handling - Implemented connection status updates for ACP agents in the bridge. - Enhanced event handling to support ACPToolCallEvent and synthetic finish actions. - Updated database schema to accommodate new ACP agent fields. - Modified API routes and handlers to authenticate internal calls using a new key. - Added tests for ACP agent registration and status publishing.
- Introduced new translations for agent types and ACP setup in Portuguese, Russian, Vietnamese, and Simplified Chinese. - Implemented the AcpBridgeSetup component for managing local ACP bridge connections. - Updated agent creation flow to include token generation for ACP agents. - Enhanced the dispatch mechanism to prefix messages with the `/paca` skill trigger for ACP agents. - Added tests for the new ACP message handling and bridge dispatch functionality.
|
Run failed. View the logs →
|
Code review — ACP agents supportThanks for this substantial feature. The local-bridge model is a good fit for letting users run agents in their own environment, but the distributed dispatch path has a few reliability and security gaps that I'd like to see tightened before merge. Critical (blocking)1. Fire-and-forget dispatch can leave conversations stuck in
2. No timeout for ACP turns
3. Daemon silently drops outbound status/event messages while disconnected
High4. Same bridge token can be used concurrently from multiple sessions
Medium5. WebSocket is accepted before credentials are verified
6. Existing bridge sessions survive token regeneration
7. Missing DB index on bridge-token hash lookup
8. API status proxy uses an
9. CORS wildcard on privileged bridge endpoints
Low10.
11.
12. Malformed
Tests
Bottom lineThe schema, service wiring, and UI look reasonable, but the distributed dispatch and message-durability issues are real blockers for a usable ACP experience. I'd recommend addressing at least the ACK/watchdog/timeout story and the single-active-session enforcement before merging.
|
…g linting, testing, and publishing to PyPI
- Introduced a timeout for HTTP calls to the AI agent service to prevent hanging requests. - Updated the agent creation logic to allow empty LLM base URLs, reflecting default behavior of certain LLM providers. - Added a new endpoint for generating ACP bridge tokens, including a background task to disconnect stale sessions. - Enhanced error handling for various agent-related errors, including invalid agent types and ACP provider issues. - Implemented CORS middleware to support an allow-list for origins, improving security. - Added tests for ACP agent creation, validation, and bridge token lifecycle to ensure proper functionality. - Created a migration to add a unique index on the acp_bridge_token_hash column to optimize lookups during WebSocket handshakes. - Established end-to-end tests for ACP agent management, including validation of agent creation and bridge token generation.
There was a problem hiding this comment.
Important
The latest commit resolves the prior review's reliability/auth concerns, but a race in token-regeneration eviction can still close a legitimate newer ACP bridge session.
Reviewed changes — the incremental diff from d055843 to cc0d86d tightened ACP bridge reliability, session binding, and API hardening.
- Replaced silent message drops with a queued outbox in
BridgeClient, soturn_statusevents survive reconnects. - Added a per-turn watchdog in
acp_dispatch.pyto fail ACP conversations that never receive a terminal status. - Enforced one active bridge session per agent via control-channel eviction and session-aware
unregister(). - Moved WebSocket credential verification before
accept()by sending the agent id and token as handshake headers. - Tightened CORS from a blanket wildcard to a configurable
CORS_ORIGINSallow-list. - Added a unique partial index on
agents.acp_bridge_token_hashso handshakes do not scan the whole table. - Fixed handler/service edge cases:
llm_base_urlis no longer required at creation, LLM/ACP fields are isolated byagent_typeon update, malformedacp_commandJSONB surfaces as an error, and the ai-agent HTTP proxy has a 10s timeout.
Kimi K2 (free via Pullfrog for OSS) | 𝕏
… agent ID and token
…ent setup - Add `splitShellCommand` function to parse shell commands while respecting quotes and whitespace. - Create unit tests for `splitShellCommand` to ensure correct functionality. - Update agent setup UI to utilize `splitShellCommand` for processing ACP commands. - Modify Caddyfile to clarify WebSocket routing for agent bridge. - Enhance agent registration logic in `acp_bridge.py` to prevent race conditions with a process-wide lock. - Implement ownership checks in WebSocket bridge route to ensure only valid events are processed. - Add comprehensive tests for the ACP bridge WebSocket route and internal HTTP endpoints. - Require non-empty ACP command for custom providers at the database level with a new migration. - Update agent repository methods to handle errors during record conversion. - Ensure agent service validations for ACP agents are robust and return appropriate errors.
There was a problem hiding this comment.
The latest incremental diff hardens the ACP bridge outbox, turn concurrency, event ownership, Caddy scope, and the custom-provider DB check. However, the token-regeneration eviction race flagged in the previous review is still present: the new token is persisted and returned before the force-disconnect runs, so a legitimate newer bridge session can be evicted if it reconnects slightly ahead of the disconnect call.
Kimi K2 (free via Pullfrog for OSS) | 𝕏
|
Clarification on review #4722784492: the suggestion block in that review was only meant to anchor the comment to the current code, not a proposed change. I’m requesting the race be fixed before merge. Issue: Fix options (either works):
Right now this is the only remaining item blocking approval of the latest incremental diff.
|

Summary
Adds ACP (Agent Client Protocol) agents — a second agent "shape" alongside the existing LLM agents. An ACP agent delegates work to a coding CLI (Claude Code, Codex, Gemini CLI, or a custom ACP server) that the user runs locally, in their own already-checked-out source folder, connected to Paca through a small local bridge daemon. No source code is cloned into Paca's infrastructure for this agent type — the bridge only relays task requests and streams conversation events back over an authenticated WebSocket.
What's new
apps/acp-bridge— new local daemon (PyPI packagepaca-acp-bridge, run viauvx), wrapping the OpenHands SDK'sACPAgent. Spawns the chosen ACP CLI as a subprocess in the current directory, streams events back to Paca, and reconnects automatically on a dropped connection.services/api—agent_type(llm/acp),acp_provider,acp_command, andacp_bridge_token_hashcolumns onagents(migration 000022); ACP-specific creation/update validation; new endpointsPOST /{agentId}/acp-bridge-token(generate a bridge token) andGET /{agentId}/acp-bridge-status(connection status). Bridge tokens are stored only as a SHA-256 hash — the plaintext is shown once at generation time.services/ai-agent— bridge connection management (acp_bridge.py), dispatch of/paca-skill-triggered messages to connected ACP agents (acp_dispatch.py), and handling ofACPToolCallEventplus synthetic finish actions in the executor/stream pipeline. A new internal API key (AI_AGENT_INTERNAL_KEY/INTERNAL_API_KEY) authenticates the API service calling back into ai-agent's internal-only routes.services/realtime— plumbing to relay ACP bridge connection status.apps/web—AcpBridgeSetupcomponent for generating/copying the local bridge run command, agent-creation flow updates to request an ACP bridge token, and translations for the new agent type/setup copy across all 9 supported locales.acp-bridge-pr-ciworkflow (ruff lint/format, pytest, package build) scoped toapps/acp-bridge/**, and apublish-acp-bridgejob incd.ymlthat publishes the package to PyPI via trusted publishing (OIDC) on release.docker-compose.*and Caddyfile updates to wire the new internal key and any related routing.Security notes
ghaccess — Paca never sees, stores, or forwards that auth, and doesn't manage or inject MCP servers/skills for ACP agents (the local ACP client's own configuration is used as-is).Testing
agent_service_test.go/agent_handler_test.gofor ACP validation and the new endpoints.test_acp_bridge.py,test_acp_dispatch.py,test_prompt.py,test_worker.py).test_bridge_client.py,test_runner.py).