Tasks, schedules, and agents API
These endpoints cover session-scoped task inspection plus managed-agent orchestration. Daemon-owned projects and project tasks now have their own separate surface. Read Projects API for that model. Sessions that are channel members can also receive daemon-created runs of kindChannelDelivery. Those runs still execute through the normal runs API and session queue. The public conversation itself lives in the separate Channels API.
Schedules, sidechains, and reviewer results can also feed public channel threads indirectly through durable channel stimuli and root-thread bindings. The schedule, task, and run themselves still remain session- and run-scoped; the channel only owns the public conversation projection.
Task endpoints
GET /v1/sessions/{session_id}/tasksGET /v1/sessions/{session_id}/tasks/{task_id}GET /v1/sessions/{session_id}/tasks/{task_id}/outputPOST /v1/sessions/{session_id}/tasks/{task_id}/stop
List and inspect tasks
GET /v1/sessions/{session_id}/tasks supports:
status: filter bypending,in_progress,blocked,completed,failed, orcancelled
TaskRecord with fields such as:
idtitledescriptionstatusowner_agent_idblocked_byblocksoutputmetadatacreated_at_msupdated_at_ms
Read task output
GET /v1/sessions/{session_id}/tasks/{task_id}/output supports:
wait: wait for output or state change before returningtimeout_ms: wait duration whenwait=truetail_bytes: excerpt size, defaulting to a small tail viewfull: include full captured output text when available
TaskOutputView:
retrieval_statustaskoutput_file_pathoutput_excerptoutput_textoutput_truncatedoutput_size_bytes
retrieval_status values include:
successnot_readytimeout
retrieval_status: "success" means the daemon read the task output view. It does not mean the task succeeded. For daemon-managed shell tasks, treat command success as task.status: "completed" plus task.metadata.exit_code: 0. If task.status is failed or cancelled, clients and agents must not report the shell task as successful even when output retrieval succeeded.
Example:
task.status: "failed" with task.metadata.terminal_reason: "daemon_restarted" and task.metadata.recovered_on_boot: true; the output endpoint still returns partial captured output when available.
Stop a task
POST /v1/sessions/{session_id}/tasks/{task_id}/stop accepts:
Schedule endpoints
GET /v1/schedulesPOST /v1/schedulesGET /v1/schedules/{schedule_id}POST /v1/schedules/{schedule_id}/cancelPOST /v1/schedules/{schedule_id}/pausePOST /v1/schedules/{schedule_id}/resumePOST /v1/schedules/{schedule_id}/trigger
GET /v1/schedules supports:
session_id
Create a schedule
POST /v1/schedules accepts a ScheduleCreateRequest.
Required fields:
nametarget_session_idcadence- exactly one of:
requestobservation_materialization
target_agent_idowner_session_idowner_agent_idcreated_by_run_idmax_executionsoverlap_policymisfire_policy
requestis a fullSubmitInputRequest- when the nested schedule request uses only
input_items, include"content": ""to match the current request shape
Cadence variants
once:
interval:
cron:
- interval cadence must be at least 5 seconds
- cron timezone defaults to
UTC max_executions, when set, must be greater than zero- when
observation_materializationis used, itstarget_session_idmust match the scheduletarget_session_id
Schedule policy fields
overlap_policy:
skipqueue_oneparallel
misfire_policy:
{ "type": "coalesce_once" }{ "type": "skip_missed" }
Schedule creation example
ScheduleView. Important fields include:
schedule_idnametarget_session_idstatuscadenceoverlap_policymisfire_policymax_executionsnext_fire_at_msqueued_fire_at_msin_flight_fire_at_msin_flight_run_idlast_fire_at_mslast_dispatched_run_idlast_errorexecution_countconsecutive_failuresrequest
ScheduleView.misfire_policy is returned with the same tagged-object shape.
Pause, resume, cancel, and manual trigger all return:
Agent endpoints
GET /v1/agentsGET /v1/agents/{agent_id}POST /v1/agents/{agent_id}/sidechainsGET /v1/agents/{agent_id}/mailboxPOST /v1/mailboxes
GET /v1/agents and GET /v1/agents/{agent_id} return ManagedAgentSnapshot records. These include the static agent record plus live state such as pending approvals, pending questions, the last assistant message, and the last runtime error.
Public channel participation does not introduce a second agent runtime. A member session still uses the normal agent snapshot, mailbox, and run queue while the daemon separately keeps the public channel log and turn leases.
Spawn a sidechain
POST /v1/agents/{agent_id}/sidechains accepts SpawnSidechainRequest.
Top-level fields:
session_idthread_idroute_policyproviderpermission_moderetentionnicknamespawn_request_idfork_contextgenerationtool_surfacecapability_scopecredential_scopesubtask
fork_context shape is:
parent_assistant_messageinherited_tool_call_idssystem_prompt
fork_context fields:
team_nameisolationprompt_merge_modeprovidergenerationtool_surfaceworktree_path
route_policyis the preferred modern form- compatibility
providerplusgenerationmay still be supplied - conflicting combinations are rejected with
400 Bad Request
- child sessions inherit the parent’s bound persona snapshot at spawn time
- child sessions also inherit the parent’s persisted capability scope
- child sessions also inherit the parent’s persisted credential scope
- child sessions inherit the parent’s effective permission mode unless
permission_moderequests a narrower mode - explicit
permission_mode: "default"is pinned as a child session override instead of falling through to the daemon global mode - sidechain spawn rejects
permission_modevalues that would widen the parent, for examplebypassPermissionsfrom adefaultparent - parent session-scoped permission updates are copied to the child session at spawn time
- when the spawn request omits
credential_scope, delegated children keep route access but lose connector credentials and credentialed MCP access by default - child
capability_scope,credential_scope, andtool_surfacecan narrow the inherited surface further but cannot widen it
Mailbox delivery
POST /v1/mailboxes posts one typed JSON envelope and returns 202 Accepted.
Example:
GET /v1/agents/{agent_id}/mailbox returns the currently queued mailbox messages without draining them. Agent-side mailbox processing drains messages through the runtime control path; this HTTP inspection endpoint is safe to repeat during debugging.
- it returns the currently queued mailbox messages
- repeat reads can return the same messages until an agent/runtime path consumes them
Evidence Note
- Code verified:
crates/kheish-daemon/src/api/handlers.rs,crates/kheish-daemon/src/main.rs,crates/kheish-daemon/src/control_tools.rs,crates/kheish-daemon/src/control_tools/tasks.rs,crates/kheish-daemon/src/services/task.rs,crates/kheish-daemon/src/state/subagent_spawn.rs,crates/kheish-daemon/src/state/session_state.rs,crates/kheish-types/src/model.rs,crates/kheish-agent/src/supervisor.rs. - CLI/API verified: task output semantics checked against
TaskOutputView; mailbox endpoint checked against HTTP handler and supervisor peek behavior. - Daemon live tested for this note: no; deterministic service tests cover failed-task output retrieval.
- Provider-specific tested for this note: no; task output retrieval is daemon-local.
