5.3 KiB
Agentctl session lifecycle (Kandev)
This document explains how agentctl fits into the Kandev execution flow, what “ready” means, and which parts of the system depend on agentctl being up.
What agentctl is
agentctl is a sidecar process that runs inside each agent container (or standalone runtime). It provides:
- HTTP API for lifecycle operations (
/health,/api/v1/start,/api/v1/stop, etc.) - ACP bridge (stdin/stdout JSON‑RPC) to the agent process (Auggie/Codex/etc.)
- WebSockets for streaming ACP updates and agent output
- Shell access to the workspace (terminal output + input)
It is the backend’s control plane for an agent execution.
High‑level flow (runtime‑agnostic)
User action (start task)
|
v
Kandev orchestrator
|
| 1) Create task session in DB
| 2) Launch agent runtime (Docker or standalone)
v
agentctl process starts
|
| 3) HTTP server comes up (health + control APIs)
v
Backend waits for agentctl readiness
|
| 4) agentctl ready => shell/workspace access available
v
ACP session initialization
|
| 5) initialize -> session/new or session/load
| 6) prompt is sent
v
Agent runs, ACP updates stream
|
| 7) session/update notifications => WS to client
v
Task session state transitions
“Ready” concepts (important distinction)
There are two different “ready” moments:
-
agentctl ready
- Meaning: agentctl HTTP server is healthy and can accept requests.
- Practical impact: shell/workspace endpoints become usable.
- Source:
lifecycle.Manager.waitForAgentctlReady. - Today: only logged; not emitted as a WS event.
-
agent ready (prompt completed)
- Meaning: agent finished the current prompt and is idle/ready for follow‑up.
- Source:
events.AgentReady(after prompt completion). - Today: internal event for orchestrator state transitions.
The frontend should not rely on “agent ready” when it needs shell access; shell access depends on agentctl readiness instead.
Current backend signals
-
agentctl readiness
agentctl is ready(agentctl client log)agentctl ready - shell/workspace access available(lifecycle manager log)
-
agent ready (post‑prompt)
events.AgentReadyinternal event (used by orchestrator state transitions)
There is no WS event that tells the client “agentctl is ready.”
Where shell streaming depends on agentctl
- Client calls
shell.subscribe(WS request) - Backend checks:
- agent execution exists for the task
- agentctl is connected
- Backend starts a streaming loop that relays agentctl shell output as
shell.outputWS notifications
If agentctl isn’t ready yet, shell.subscribe fails and the frontend currently retries.
Suggested improvement (optional)
Introduce a WS notification like:
{ "action": "task.session.agentctl_ready", "payload": { "task_id": "...", "task_session_id": "..." } }
So the client can subscribe once and only request shell after it receives readiness.
End‑to‑end diagram (detailed)
Client Backend (Kandev) agentctl Agent
| | | |
| orchestrator.start | | |
|------------------------------->| | |
| | create task session | |
| | launch runtime | |
| |---------------------------->| process starts |
| | | HTTP server up |
| | waitForAgentctlReady | |
| |---------------------------->| /health |
| |<----------------------------| 200 OK |
| | (agentctl ready) | |
| | ACP initialize | |
| |---------------------------->| initialize |
| | ACP session/new | |
| |---------------------------->| session/new |
| | ACP prompt | |
| |---------------------------->| session/prompt |
| | |--------------------->|
| | | agent runs |
| | WS stream | |
|<-------------------------------| (session/update notifications) |
References
apps/backend/internal/agent/lifecycle/manager.go(waitForAgentctlReady)apps/backend/internal/agentctl/client/client.go(WaitForReady)apps/backend/internal/agent/handlers/shell_handlers.go(shell.subscribe)apps/backend/internal/events/types.go(AgentReady)