Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
8757498
feat(interface): mock autonomy panel
jamiepine Aug 9, 2026
3c437e8
docs: wakes design
jamiepine Aug 9, 2026
c22bf33
feat(interface): wakes card and run provenance in autonomy panel
jamiepine Aug 9, 2026
04c48a8
docs: ground wakes design in existing architecture
jamiepine Aug 9, 2026
500c6e5
feat(interface): split autonomy into fleet view and per-agent screen
jamiepine Aug 9, 2026
b87ce12
feat(tasks): failed status and nullable assignment
jamiepine Aug 9, 2026
ef6230f
feat(wakes): typed event vocabulary and persisted wake-event queue
jamiepine Aug 9, 2026
6436547
refactor(channel): explicit ChannelKind over cron_outcome discriminators
jamiepine Aug 9, 2026
cd91ff5
feat(goals): instance-scoped goals with tools, prompt injection, and API
jamiepine Aug 9, 2026
8401d0a
feat(autonomy): autonomy channel, level dial, and run history
jamiepine Aug 9, 2026
e117dad
feat(autonomy): API surface and live panel
jamiepine Aug 9, 2026
4a4ce0b
docs: dormancy, durable transcript, and prompt stability designs
jamiepine Aug 9, 2026
1d1d200
Merge branch 'main' into jamiepine/autonomy-panel
jamiepine Aug 9, 2026
9c00b35
feat(wakes): wake definitions, config seeding, and briefing instructions
jamiepine Aug 9, 2026
b2febc7
feat(wakes): producers, schedule firing, wakes API, and instance ceiling
jamiepine Aug 10, 2026
3844c11
Merge remote-tracking branch 'origin/jamiepine/autonomy-panel' into j…
jamiepine Aug 10, 2026
f8da371
fix(autonomy): address review findings
jamiepine Aug 10, 2026
c9e5492
fix(ci): collapse wake reconcile conditional and await skill usage se…
jamiepine Aug 10, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions docs/design-docs/autonomy.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ This has a well-known failure mode: the agent writes malformed JSON, overwrites

The autonomy channel is the agent's process for self-directed work. It is not per-task. It is one channel that wakes on a configured interval, surveys the task state, does as much enrichment and preparation as useful, executes ready tasks if any exist, and exits. On the next interval it wakes again.

The interval is the default trigger, not the only one. Wake events — schedules, webhooks, internal events like a task approval or a user comment, and idle/staleness conditions — pull the next run forward and appear in its context with their payloads and instructions. The channel is the single consumer of all wake sources; see [`wakes.md`](wakes.md) for the trigger model, queue semantics, and authority rules.

It is structurally similar to a cron channel — periodic, no user present, full agent context. The difference is that it is persistent across runs and has awareness of its own history.

The autonomy channel is the only process that:
Expand All @@ -37,6 +39,7 @@ The cortex assembles the autonomy channel's context before each wake. It gets:
- **Identity** — SOUL.md, IDENTITY.md, ROLE.md. The agent knows who it is.
- **Memory bulletin** — the cortex's current knowledge synthesis.
- **Working memory** — recent system events. What's been happening across all channels.
- **Wake events** — what pulled this run forward, if anything: the wake's name, instructions, and payload for each pending event since the last run. Surfaced first, because they are usually why the run exists.
- **Task state** — all active tasks: ready, in-progress, backlog, pending_approval. Full detail on each, including all comments.
- **Goals** — all active goals with descriptions and notes. Background context and direction, not a work queue. See [`goals.md`](goals.md).
- **Active workers** — what's currently running so it doesn't duplicate work.
Expand Down Expand Up @@ -137,6 +140,8 @@ ALTER TABLE tasks ADD COLUMN last_enriched_at TEXT;

Tasks have an `assigned_agent_id` field. Once an agent claims a task, no other agent can work on it. Ownership is enforced at the query level and set atomically when a task is first enriched or executed.

The global tasks table currently declares `assigned_agent_id TEXT NOT NULL` with assignment at creation time, so the unowned-task model requires making the column nullable. That migration touches the global database and every task consumer; it ships as its own change ahead of this system, not inside it.

```sql
-- Atomic claim: only succeeds if still unassigned or already assigned to this agent
UPDATE tasks SET assigned_agent_id = ?1
Expand Down Expand Up @@ -180,15 +185,15 @@ Do not start a new task.

The channel wraps up gracefully and exits cleanly. The hard `timeout_secs` remains as a safety net but should almost never fire.

This uses the existing addendum context delivery mechanism (same path as worker context injection).
Delivery mechanism: a synthetic system message between turns, the same pattern the cron scheduler uses for its timeout wrap-up injection. The worker-style mid-turn injection hook (`inject_rx` on `SpacebotHook`) is wired only for workers today; giving `Channel` the same pair would let the warning land inside a live turn, but that is an enhancement, not a prerequisite.

---

## Continuity Between Runs

**Task comments** — the primary record of what has been investigated and found. Persist indefinitely. The next run sees all prior comments when it reads task state on wake, so it does not duplicate completed investigation.

**Run summaries** — on exit, `autonomy_complete` records what was enriched, what was executed, what was created. The next wake receives the last `run_history_count` summaries as part of its context.
**Run summaries** — on exit, `autonomy_complete` records what was enriched, what was executed, what was created, and which wake events the run consumed. The next wake receives the last `run_history_count` summaries as part of its context, and the UI renders the consumed wakes as "woken by" provenance per run.

Working memory provides broader system context. Run summaries provide the autonomy-specific thread.

Expand All @@ -199,6 +204,7 @@ Working memory provides broader system context. Run summaries provide the autono
```
Cortex tick
→ elapsed since last autonomy run >= interval_secs
OR unconsumed wake events are pending
→ no autonomy channel currently running
→ autonomy.enabled = true
Expand All @@ -221,7 +227,7 @@ Calls set_outcome → summary recorded
Channel exits → cortex records last_run_at, cleans up
```

If the channel crashes mid-execution, the task returns to `ready`. If a task fails 3 consecutive times, it moves to `failed` and emits a working memory `Error` event. Enrichment runs (comments only) do not count as failures.
If the channel crashes mid-execution, the task returns to `ready`. If a task fails 3 consecutive times, it moves to `failed` and emits a working memory `Error` event. Enrichment runs (comments only) do not count as failures. `failed` is a new `TaskStatus` variant — the current set is pending_approval, backlog, ready, in_progress, done — so adding it includes the transition table, API, and UI sweep.

---

Expand Down Expand Up @@ -258,7 +264,7 @@ Enforced at startup and on config reload — autonomy does not start if any rule
- `autonomy_channel.md.j2` system prompt (enrichment-first, `autonomy_complete` on exit, never execute `pending_approval`)
- Goals table migration + `goal_create`, `goal_update`, `goal_list` tools (see `goals.md`)
- Cortex: interval trigger, `last_run_at` tracking, context assembly, channel lifecycle, soft timeout addendum at `warn_secs`
- `autonomy_complete` tool + run summary storage + retrieval for run history (note: `set_outcome` already exists for cron delivery — `autonomy_complete` is intentionally distinct)
- `autonomy_complete` tool + run summary storage + retrieval for run history. Intentionally distinct from `set_outcome`, which is an unpersisted last-write-wins delivery buffer with no completion contract. Model it on `memory_persistence_complete` instead, which already enforces call-the-terminal-tool-before-exit through the hook retry machinery.
- `last_enriched_at` column on tasks; atomic claim via `assigned_agent_id`; selection query with priority ordering
- Task retry/failure handling (3 strikes → `failed`, working memory error event)
- All config fields + validation
Expand Down
Loading
Loading