Sessions and claims
A session queues work for an agent. A claim is the active lease that lets one eligible worker execute that session. Keeping them separate prevents duplicate runs and accidental execution.
If you are implementing the worker loop, read this page with Build a local agent worker.
Desktop and the CLI use the same lifecycle. Creating or starting a local worker from Desktop does not bypass claims. It starts a process that can heartbeat, poll, and claim sessions for the signed-in owner.
Session creation is not execution
Creating a session queues work. A worker starts only after One Horizon accepts a claim request for that session.
Sessions can store:
- Workspace and agent IDs
- Execution mode, either
localorcloud - Initiating user
- Local owner user for local sessions
- Target task or initiative
- Prompt
- Trusted instructions
- Untrusted context
- Active claim ID
- Plan, external URL, error message, and timestamps
Session states
Agent sessions use these lifecycle states:
stateDiagram-v2 [*] --> queued queued --> pending queued --> active: claim pending --> queued active --> awaiting_input awaiting_input --> active active --> complete active --> error active --> stale queued --> cancelled pending --> cancelled active --> cancelled stale --> queued: retry complete --> [*] error --> [*] cancelled --> [*]
| State | Meaning |
|---|---|
queued | Waiting for an eligible worker to claim it. |
pending | Accepted by the platform but not ready to execute yet. |
active | A worker holds an active claim and is executing. |
awaiting_input | The worker needs user input before it can continue. |
complete | Work finished successfully. |
error | Work failed or could not be completed. |
stale | A worker stopped heartbeating or the claim expired. |
cancelled | The user or system cancelled the session. |
Claim rules
A work claim is scoped to one workspace, agent, worker, and session. The claim proves that a worker is allowed to execute that session right now.
When a worker claims a session, the platform validates that:
- The worker belongs to the same workspace and agent.
- The worker's execution mode matches the session.
- A local worker is owned by the authenticated user.
- The session does not already have another active claim.
- Any stale active claim can be expired or released before a new claim starts.
Pass leaseSeconds in the claim request to control how long the lease is valid. The default is 900 seconds (15 minutes). If the lease expires before the worker completes, fails, or releases the session, the platform marks the session stale and returns it to the claimable pool. Any eligible worker can claim a stale session on its next poll.
Every session update must include the claimId from the claim response. This includes activities, patches, completion, failure, and release. Calls without the active claimId are rejected.
Two workers for the same agent should not execute the same session at the same time. Different agents can still work on the same underlying task through separate sessions.
Activities
Workers emit activities while handling a claimed session. Activities provide visible progress and audit context.
Activity types include:
progressplan_updatedexternal_url_updatedawaiting_inputcompletedfailedpolicy_decision
Emit meaningful changes. Do not turn every heartbeat into an activity.
Complete, fail, or release
Completing a session closes the active claim and marks the session complete.
Failing a session closes the active claim, records the error, and marks the session error.
Releasing a session closes the active claim without marking the work done. A released session can return to the queue for another eligible claim.
When a worker stops heartbeating, the platform can mark the worker or session stale so the work can be inspected or retried.
Automatic task updates
When your agent blueprint is configured with task update rules, One Horizon applies task state transitions automatically based on session lifecycle events. Workers do not write to the task tracker directly.
Default task update behavior:
| Session event | Task state applied |
|---|---|
| Session claimed | in_progress |
| Session completed | review |
| Session awaiting input | blocked |
| Retries exhausted | blocked |
Agent blueprints set these defaults. Worker runtime configuration can narrow the allowed updates but cannot expand them beyond what the blueprint permits.
API shape
Agent work endpoints live under:
/api/v1/workspaces/{workspaceId}/agentsCommon operations include:
- List or create agent profiles.
- Register, heartbeat, list, update, or delete workers for an agent.
- Create, list, or fetch sessions for an agent.
- Poll sessions visible to a specific worker.
- Claim, update, release, complete, or fail a worker-scoped session.
- Cancel a visible session.
- Emit activities for a claimed session.
See the API reference for operation names, request bodies, response bodies, and SDK types.
API behavior to know
Agent work endpoints require OAuth user tokens. Workspace API keys cannot register local workers, claim sessions, emit activities, or call worker-scoped session endpoints.
Local visibility is owner-only. Creating a local session requires the local owner to match the authenticated user, and polling or claiming local work requires the worker owner to match the authenticated user.
Desktop worker setup uses the signed-in user's OAuth session. It can create and start that user's own local worker, but it cannot start a local process on another user's machine.
Session updates and activity writes are tied to active claims. A worker can update plan or external URL metadata, emit progress, complete work, fail work, or release the claim only after the platform accepts the claim for that session.
Claims are leases, not permanent ownership. If a worker stops heartbeating, disconnects, releases work, or lets a claim expire, the platform can mark the worker or session stale so the work can be inspected or retried.
Webhooks for cloud workers
Cloud workers may receive agent.session_queued as a notification that work exists. That webhook is not the execution authority. A cloud worker still needs to fetch and claim the session through the REST API before running.