Agent run
A run is one isolated execution of an agent against a task, realized as a Kubernetes Job.
The nine steps
1. Nexus loads agent definition from MongoDB
2. Nexus loads attached skills
3. Nexus searches memory for relevant context
4. Nexus builds runtime prompt/config
5. Nexus creates Kubernetes Job
6. Agent runs in isolated pod
7. Agent reports events back to Nexus
8. Nexus updates internal board
9. Nexus syncs to Taiga
The crucial property: the pod does not need to know all agent types. It receives a config payload.
The run config payload
{
"run_id": "run_123",
"agent_id": "agent_backend_implementer",
"task_id": "task_456",
"system_prompt": "...",
"skills": ["...skill markdown..."],
"memory": ["...relevant memory..."],
"tools": ["git", "shell", "cargo"],
"repositories": [
{ "url": "https://github.com/acme/backend.git", "dir": "backend", "branch": "main" },
{ "url": "https://github.com/acme/docs.git", "dir": "docs", "read_only": true }
],
"permissions": {
"can_commit": true,
"can_merge": false
}
}
The same nexus-agent-runner image becomes a planner, implementer, reviewer,
tester, or devops agent depending on this payload.
Team routing (which agent gets the task)
The worker leases ready_for_agent tasks to a team of role-specialized
agents rather than a single agent:
- Dependency-aware — a task is held until every task in its
depends_onisdone, so an architecture task can gate the implementation tasks behind it. - Role match — only enabled agents whose SOUL
rolematches the task's role are considered. - Load-balanced — among matching agents, the least-loaded one (fewest
queued/runningruns) is chosen; agents already atNEXUS_AGENT_MAX_CONCURRENCY(default 3) are skipped. If the whole team is at capacity the task simply waits for the next tick.
This is what lets a goal fan out across a coordinated team of agents working in parallel within their limits.
Inside the runner
The nexus-agent-runner pod:
- Loads the run config.
- Loads skills and memory.
- Clones every configured repository side-by-side into the workspace (git CLI inside the container), then adds a "Repositories" section to the prompt listing each checkout path so the agent knows where each repo lives.
- Calls the LLM (via the
nexus-llmprovider abstraction). For API backends this is a bounded tool-calling loop: the model calls tools and reads results until it emits a final result. - Runs tools (only those granted and passing their gate; the
shell.exectool enforces a hardline command firewall, and platform tools likememory.proposeare proxied to Core over NATS where permissions are re-checked). Gated actions raise approvals. - Commits changes / opens a PR if permitted.
- Streams logs and structured events back to Nexus.
- Returns a structured result.
Events
Runs emit durable events on NATS JetStream:
nexus.agent.run.started
nexus.agent.run.completed
nexus.agent.run.failed
Core consumes these to update agent_runs, the board, and Taiga. Because
JetStream is durable, a Core restart replays missed events.
Cancellation and logs
The AgentRuntime trait exposes cancel_run and get_logs/stream_logs. The
Kubernetes implementation deletes the Job and streams pod logs.
#[async_trait::async_trait]
pub trait AgentRuntime {
async fn start_run(&self, request: AgentRunRequest) -> anyhow::Result<AgentRunHandle>;
async fn cancel_run(&self, run_id: &str) -> anyhow::Result<()>;
async fn stream_logs(&self, run_id: &str) -> anyhow::Result<()>;
}