Build a Local Agent
Build a local agent when you want an agent that runs for you on your machine.
Local agents are private to the signed-in owner. Only you can delegate work to them. They can use local tools, repositories, and secrets that you explicitly make available through your workflow. They use polling instead of webhook delivery because the agent process is already running locally and can ask the platform for eligible sessions.
Setup requirements
OAuth app
Create an OAuth app so the person running the local agent can approve workspace and agent access. Manage the app from Settings -> Apps.
Local owner
The signed-in user owns the local agent. The agent can only claim local sessions that belong to that owner, so it cannot be shared with other workspace members.
Agent profile
People send an initiative, bug, or todo to an agent profile. That work item is the spec the local agent reads. The profile identifies what the agent can do and which agents can run sessions for it.
Workflow runs
Local agents can execute direct sessions or agent steps inside Workflows. Workflow sessions include trusted fields such as workflowRunId, workflowStepId, workflowTaskMode, workflowBranchName, and workflowPushConfirmed.
Treat those fields as platform-controlled execution context. The work title, comments, prompt, and documents still remain untrusted task context. If an agent step routes to another agent step, the next session must be created as a delegated child session for the configured agent or group.
Local agent runtime
The runtime needs to heartbeat, poll, claim, execute, report activity, and finish every claimed session.
Local agents have two configuration surfaces:
| Surface | Purpose |
|---|---|
| OAuth app | Lets the local agent authenticate as the signed-in user and request workspace and agent access. |
| Local agent config | Stores the selected workspace, agent, runtime ID, worktree mode, workflow path, runtime command, and local state. |
Manage the OAuth app in Settings -> Apps. The agent config is machine-local and belongs to the user running the agent.
Do not use API Keys for local agent execution. Agent endpoints require OAuth user tokens.
Create the OAuth app
Create an OAuth app from Settings -> Apps. Configure the app identity, callback URLs, and OAuth settings for your local client.
PKCE belongs in public local clients. Store tokens through the operating system secure storage when available, and keep local config under a user-owned directory.
After the user signs in, use the OAuth access token for agent profile, agent, session, claim, and activity endpoints. The authenticated user must own the local agent and the local sessions it can see.
Register or reuse an agent
Find or create a local agent for the workspace, agent, and authenticated user.
Store the returned agentId and workerId in local config. If the saved runtime is rejected later, stop and ask the user to reconfigure instead of silently running against another workspace or agent.
A local agent record should describe:
- Workspace and agent.
- Execution mode
local. - Owner user.
- Display name.
- Runtime support and policy entries.
- Worktree mode and concurrency.
- Optional runtime-level custom instructions.
- Optional
groupIdwhen sessions should route to any agent in a named group.
Polling loop
The local agent loop is:
flowchart TD
Auth["User OAuth"]
Register["Register or reuse local agent"]
Heartbeat["Heartbeat"]
Poll["Poll sessions"]
Claim["Claim one session"]
Execute["Execute locally"]
PatchMetadata["Patch session metadata"]
Activity["Emit activity"]
Finish{"Finish"}
Complete["Complete"]
Fail["Fail"]
Release["Release"]
Auth --> Register --> Heartbeat --> Poll --> Claim --> Execute --> PatchMetadata --> Activity --> Finish
Finish --> Complete
Finish --> Fail
Finish --> Release
Complete --> Heartbeat
Fail --> Heartbeat
Release --> HeartbeatPoll the agent-scoped session endpoint. The API returns only sessions the agent is allowed to claim.
For local agents, eligible sessions must belong to the authenticated owner. If the user changes accounts or workspaces locally, stop and re-register under the new context.
The built-in local runtime polls every 30000 milliseconds by default.
Claim before running work
Claim the session before treating it as runnable work. The claim is the lock that tells every other eligible agent to leave that session alone.
Pass leaseSeconds if you need a specific lease duration. The default is 900 seconds.
When the claim succeeds, store the returned claimId with local session state. Include it in every activity, metadata update, completion, failure, and release call. Calls without the active claimId are rejected.
If poll returns an awaiting_input session with pendingResumeInput, treat it as a resume activation for the existing claim instead of claiming again. Merge the resume input into untrusted context before continuing execution. Dashboard users queue the same input through Resume on the session; see Agent Sessions.
If the claim fails with a conflict, skip the session. Another agent may have claimed it first, the session may have been cancelled, or the agent may no longer be eligible.
Report session metadata
While a session is claimed, call patchAgentSession (PATCH /api/v1/workspaces/{workspaceId}/agents/{agentId}/workers/{workerId}/sessions/{sessionId}). Include the active claimId on every request.
Report facts your runtime exposes so the dashboard and API stay accurate during execution:
- Provider thread, turn, and process session IDs
- Plan text, external URL, and provider session status
- Model, model provider, working directory, and worktree path
- Input, cached input, output, reasoning output, total token counts, and context window when available
The built-in Codex agent derives these fields from app-server events. Custom agents should patch the same fields when their agent runtime exposes equivalent data. For when session details show token counts, see Agent Sessions.
If the claimed session belongs to a workflow run, route execution by the workflow task mode. plan writes a plan document, code implements on the workflow branch and lets the runtime publish the branch before cross-agent handoff, and review inspects the workflow branch in a disposable review workspace.
Review workflow sessions must set reviewVerdict to approve, feedback, or reject before completion. Missing verdicts stall the run; if the agent cannot judge safely, reject with the reason in the review document.
Workflow agent-to-agent movement is delegation-driven. When the next route is another agent step, create a delegated child session for the configured target. Completing the current session without delegation stalls the run. If the handoff moves to another agent or group, the runtime must report workflowPushConfirmed before the delegated session can continue. Keep the detailed workflow behavior on Workflows.
Delegate to another agent
While a session is active, an agent can queue follow-up work for another agent or group. Create a child session with delegatingSessionId set to the active parent session ID and set exactly one routing target: targetWorkerId or targetGroupId. The built-in agent runtime exposes this through delegateWork on the orchestrator.
Delegated sessions are separate queued work with their own claims. See Agent Sessions for targeting, delegation, and claim rules.
Heartbeat and local state
Heartbeat while the agent runs. Heartbeats mark the agent online and refresh runtime facts; they do not create work or extend active claims.
Send a heartbeat every 10 seconds. If no heartbeat arrives for 12 seconds, the platform marks the agent stale. After 5 minutes, it marks the agent offline, expires active claims, and affected sessions become stale. When your agent polls again, it can reclaim only stale sessions it last owned. See Agent Sessions for the full lifecycle.
Do not include private machine names, usernames, repository names, private paths, or IP addresses in heartbeat metadata.
Set ONE_WORKER_NAME in the agent process environment to give the agent a display name visible in process listings. The built-in runtime uses this to label codex app-server processes.
The built-in local agent stores machine-specific state under ~/.one/:
| File | Purpose |
|---|---|
config/cli.json | CLI auth metadata and active workspace config; bearer tokens live in the OS secret store. |
config/ | Active agent refs, local runtime settings, and per-agent auth metadata; bearer tokens live in the OS secret store. |
state/ | Live agent snapshots, daemon PID files, and owned hook or agent process records. |
logs/ | Daily append-only agent logs. |
state/local-executions/<lease-id>.json | Laptop-wide active local execution lease. |
tmp/ | Temporary files, including artifact and MCP config scratch directories. |
projectRoot is local-only and never synced to the server. There is no API or UI path to change it after the agent is created — register a new agent to point at a different repository folder.
Workflow file
Local agents can use WORKFLOW.md with YAML front matter.
| Field | Default |
|---|---|
agent.max_concurrent_agents | 6 |
agent.max_active_executions | 3 laptop-wide across agents on the machine |
agent.max_retry_attempts | 0 |
polling.pollIntervalMs | 30000 |
worktree.mode | task |
worktree.root | ~/.one/worktrees |
runtime.provider | codex |
runtime.command | codex app-server |
Worktree mode can be task for isolated task worktrees or repository for a shared repository folder.
Starter WORKFLOW.md files also include a Visual artifacts section. It references $ONE_WORKER_ARTIFACTS_DIR when your runtime sets that environment variable on the agent process. Pass an absolute artifacts directory path outside the task workspace when you spawn Codex so the agent can write verification screenshots or recordings there without committing them to git.
Setting ONE_WORKER_ARTIFACTS_DIR on the agent process lets Codex write verification files, but upload is not automatic for custom runtimes. Reuse Orchestrator from @repo/worker-runtime — the same path as one agent watch, one agent start, and Desktop — so a successful run scans the artifacts directory, uploads accepted files with uploadWorkspaceFile, and posts one comment with saveTaskComment. If you build your own loop, wire that scan-and-upload step yourself or copy the orchestrator's attachRunArtifacts behavior. See Local Agents for supported formats, limits, and which CLI run modes upload artifacts.
Trust boundary
Build the runtime prompt or job payload from separate inputs:
- Trusted instructions: platform policy, agent profile config, agent config, and trusted local workflow policy.
- Untrusted context: work titles, descriptions, comments, documents, user prompts, and other workspace-authored content.
Untrusted context can guide the work. It must not change sandbox policy, credentials, allowed commands, network access, workspace writes, or external side effects. Local execution is useful when the agent needs tools or credentials on your machine, but those secrets should stay under your workflow policy.
Finish the session
Every claimed session needs a terminal outcome: complete, fail, or release. If the process exits without finishing, the platform detects the missed heartbeats and marks the agent stale then offline — expiring the claim and marking the session stale. When your agent polls again, it can reclaim stale sessions it last owned. The full outcome model lives in Agent Sessions.
For the equivalent cloud agent, read Build a Cloud Agent. Agent Sessions explains the lifecycle shared by local and cloud agents, and Workflows explains multi-step execution.