From f54881a60252d9dcba78ab339c41901b9c27591c Mon Sep 17 00:00:00 2001 From: Vikas Singhal Date: Thu, 17 Sep 2026 16:02:40 +0530 Subject: [PATCH] fix(agents): operating notes match the real tool surface (v0.445.1) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Stale ask→ask_human in the team section, agent-filed tasks are proposals, delegation framed by cost, denial/credential/memory-hygiene guidance added. context-injection-test now checks the whole assembled prompt and runs in test:governance. Co-Authored-By: Claude Opus 5 (1M context) --- CHANGELOG.md | 15 +++ package-lock.json | 4 +- package.json | 4 +- scripts/context-injection-test.cjs | 9 +- src/terminal.ts | 153 +++++++++++++++-------------- 5 files changed, 107 insertions(+), 78 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 540c9b7b..5c9bc049 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,21 @@ new version heading in the same commit. ## [Unreleased] +## [0.445.1] - 2026-09-17 +### Fixed +- **Agent operating notes brought back in line with the tools agents actually have.** The OS-owned + orientation every claude-code agent receives had drifted: the team section still told agents to call + `ask` (renamed `ask_human` in v0.399.0), the notes and fleet roster said an unassigned task "just waits + for someone to pick it up" (an agent-filed task without `autoDispatch` is a PROPOSAL held for a human), + and they pushed delegation as the default when agent→agent hand-offs are the fleet's largest cost. + The notes now: treat a denial as a decision (never route around it; `policy_propose`/`host_propose` + instead), steer credentials to `secret_request`/`connection_request` rather than chat, name + `revise`/`forget`, `session_history`, `check_inbox`, `update` progress, `blockedOn`, and give a + delegation ladder (do it yourself → `ask_agent` → `task_create` with `wait` → durable hand-off). + `scripts/context-injection-test.cjs` now checks every tool named in the WHOLE assembled prompt (it only + read the notes, which is how the stale `ask` survived) and runs in `npm run test:governance` — it had + never been wired in. + ## [0.445.0] - 2026-09-17 ### Added - **Edit an automation by talking it through with its agent.** Automations → ⋯ → **Edit with agent…** opens diff --git a/package-lock.json b/package-lock.json index 776d1987..bd7a77b3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "agent-os", - "version": "0.445.0", + "version": "0.445.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "agent-os", - "version": "0.445.0", + "version": "0.445.1", "license": "MIT", "bin": { "agent-os": "bin/agent-os" diff --git a/package.json b/package.json index 9b8ec5ad..509c313f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "agent-os", - "version": "0.445.0", + "version": "0.445.1", "description": "A generic, governed operating system for running autonomous agents safely across brands. Ships with a local web console.", "license": "MIT", "type": "commonjs", @@ -27,7 +27,7 @@ "check-deps": "bash scripts/install-deps.sh --check", "dev": "ts-node src/cli.ts serve", "demo:dev": "ts-node src/demo.ts", - "test:governance": "node scripts/version-sync-test.cjs && node scripts/governance-conformance.cjs && node scripts/tier-a-policy-test.cjs && node scripts/policy-baseline-test.cjs && node scripts/heredoc-intent-test.cjs && node scripts/capability-registry-test.cjs && node scripts/composio-envelope-test.cjs && node scripts/composio-identity-test.cjs && node scripts/idle-reaper-test.cjs && node scripts/dm-continuity-test.cjs && node scripts/telegram-dm-lane-test.cjs && node scripts/cli-link-origin-test.cjs && node scripts/alert-staleness-test.cjs && node scripts/run-as-identity-test.cjs && node scripts/email-identity-guard-test.cjs && node scripts/deps-freshness-test.cjs && node scripts/runtime-account-test.cjs && node scripts/runtime-account-misattribution-test.cjs && node scripts/runtime-usage-refresh-test.cjs && node scripts/keychain-credential-test.cjs && node scripts/credential-preflight-test.cjs && node scripts/runtime-login-test.cjs && node scripts/rotate-on-reload-test.cjs && node scripts/headless-resumable-test.cjs && node scripts/session-revive-gates-test.cjs && node scripts/claude-config-seed-test.cjs && node scripts/claude-config-isolation-test.cjs && node scripts/output-style-test.cjs && node scripts/session-cost-test.cjs && node scripts/chain-model-test.cjs && node scripts/task-workers-test.cjs && node scripts/tuning-patch-test.cjs && node scripts/task-runs-test.cjs && node scripts/task-pr-links-test.cjs && node scripts/task-draft-delete-test.cjs && node scripts/task-discussion-delivery-test.cjs && node scripts/task-resume-test.cjs && node scripts/task-unblock-test.cjs && node scripts/audience-session-access-test.cjs && node scripts/warm-chat-test.cjs && node scripts/poke-warm-caller-test.cjs && node scripts/wakeup-queue-test.cjs && node scripts/stranded-human-stop-test.cjs && node scripts/inject-submit-test.cjs && node scripts/blocked-routing-test.cjs && node scripts/self-dispatch-guard-test.cjs && node scripts/task-proposals-test.cjs && node scripts/npm-boundary-test.cjs && node scripts/agent-edit-guard-test.cjs && node scripts/per-agent-context-test.cjs && node scripts/goal-update-guard-test.cjs && node scripts/insights-signal-test.cjs && node scripts/outcome-derivation-test.cjs && node scripts/episode-quality-test.cjs && node scripts/memory-upkeep-test.cjs && node scripts/automem-health-test.cjs && node scripts/memory-store-switch-test.cjs && node scripts/memory-preload-test.cjs && node scripts/turn-lifecycle-test.cjs && node scripts/resume-seed-test.cjs && node scripts/outcome-vocabulary-test.cjs && node scripts/skill-presets-test.cjs && node scripts/skill-edit-proposal-test.cjs && node scripts/notify-hook-route-test.cjs && node scripts/review-notify-test.cjs && node scripts/turn-idle-background-guard-test.cjs && node scripts/waiting-brief-test.cjs && node scripts/runtime-death-alert-test.cjs && node scripts/github-per-member-test.cjs && node scripts/github-multi-org-test.cjs && node scripts/card-measurement-test.cjs && node scripts/scheduler-admission-test.cjs && node scripts/tick-liveness-test.cjs && node scripts/audit-mirror-test.cjs && node scripts/request-metrics-test.cjs && node scripts/tool-usage-test.cjs && node scripts/sessions-list-perf-test.cjs && node scripts/summarizer-degradation-test.cjs && node scripts/agent-history-scope-test.cjs && node scripts/webhook-ingress-test.cjs && node scripts/slack-content-filter-test.cjs && node scripts/slack-ingress-test.cjs && node scripts/discord-ingress-test.cjs && node scripts/chat-attachments-test.cjs && node scripts/clickup-task-bridge-test.cjs && node scripts/agentric-commands-test.cjs && node scripts/whats-new-test.cjs && node scripts/opencode-gate-test.cjs && node scripts/protected-path-guard-test.cjs && node scripts/attach-grace-test.cjs && node scripts/attach-file-liveness-test.cjs && node scripts/feed-smoke.cjs && node scripts/activity-classify-test.cjs && node scripts/goal-room-test.cjs && node scripts/secret-rotation-test.cjs && node scripts/update-watch-test.cjs && node scripts/runtime-update-watch-test.cjs && node scripts/setup-wizard-test.cjs && node scripts/md-pdf-test.cjs && node scripts/proposal-surfacing-test.cjs && node scripts/process-janitor-test.cjs && node scripts/detached-work-steer-test.cjs && node scripts/statusline-install-test.cjs && node scripts/docs-create-agent-test.cjs && node scripts/agent-stats-rollup-test.cjs && node scripts/task-discussion-rollup-test.cjs && node scripts/session-insights-stamp-test.cjs && node scripts/loop-stall-attribution-test.cjs && node scripts/session-progress-test.cjs && node scripts/goal-metric-review-test.cjs && node scripts/capability-gap-test.cjs && node scripts/workflow-proposal-test.cjs && node scripts/automation-edit-proposal-test.cjs", + "test:governance": "node scripts/version-sync-test.cjs && node scripts/context-injection-test.cjs && node scripts/governance-conformance.cjs && node scripts/tier-a-policy-test.cjs && node scripts/policy-baseline-test.cjs && node scripts/heredoc-intent-test.cjs && node scripts/capability-registry-test.cjs && node scripts/composio-envelope-test.cjs && node scripts/composio-identity-test.cjs && node scripts/idle-reaper-test.cjs && node scripts/dm-continuity-test.cjs && node scripts/telegram-dm-lane-test.cjs && node scripts/cli-link-origin-test.cjs && node scripts/alert-staleness-test.cjs && node scripts/run-as-identity-test.cjs && node scripts/email-identity-guard-test.cjs && node scripts/deps-freshness-test.cjs && node scripts/runtime-account-test.cjs && node scripts/runtime-account-misattribution-test.cjs && node scripts/runtime-usage-refresh-test.cjs && node scripts/keychain-credential-test.cjs && node scripts/credential-preflight-test.cjs && node scripts/runtime-login-test.cjs && node scripts/rotate-on-reload-test.cjs && node scripts/headless-resumable-test.cjs && node scripts/session-revive-gates-test.cjs && node scripts/claude-config-seed-test.cjs && node scripts/claude-config-isolation-test.cjs && node scripts/output-style-test.cjs && node scripts/session-cost-test.cjs && node scripts/chain-model-test.cjs && node scripts/task-workers-test.cjs && node scripts/tuning-patch-test.cjs && node scripts/task-runs-test.cjs && node scripts/task-pr-links-test.cjs && node scripts/task-draft-delete-test.cjs && node scripts/task-discussion-delivery-test.cjs && node scripts/task-resume-test.cjs && node scripts/task-unblock-test.cjs && node scripts/audience-session-access-test.cjs && node scripts/warm-chat-test.cjs && node scripts/poke-warm-caller-test.cjs && node scripts/wakeup-queue-test.cjs && node scripts/stranded-human-stop-test.cjs && node scripts/inject-submit-test.cjs && node scripts/blocked-routing-test.cjs && node scripts/self-dispatch-guard-test.cjs && node scripts/task-proposals-test.cjs && node scripts/npm-boundary-test.cjs && node scripts/agent-edit-guard-test.cjs && node scripts/per-agent-context-test.cjs && node scripts/goal-update-guard-test.cjs && node scripts/insights-signal-test.cjs && node scripts/outcome-derivation-test.cjs && node scripts/episode-quality-test.cjs && node scripts/memory-upkeep-test.cjs && node scripts/automem-health-test.cjs && node scripts/memory-store-switch-test.cjs && node scripts/memory-preload-test.cjs && node scripts/turn-lifecycle-test.cjs && node scripts/resume-seed-test.cjs && node scripts/outcome-vocabulary-test.cjs && node scripts/skill-presets-test.cjs && node scripts/skill-edit-proposal-test.cjs && node scripts/notify-hook-route-test.cjs && node scripts/review-notify-test.cjs && node scripts/turn-idle-background-guard-test.cjs && node scripts/waiting-brief-test.cjs && node scripts/runtime-death-alert-test.cjs && node scripts/github-per-member-test.cjs && node scripts/github-multi-org-test.cjs && node scripts/card-measurement-test.cjs && node scripts/scheduler-admission-test.cjs && node scripts/tick-liveness-test.cjs && node scripts/audit-mirror-test.cjs && node scripts/request-metrics-test.cjs && node scripts/tool-usage-test.cjs && node scripts/sessions-list-perf-test.cjs && node scripts/summarizer-degradation-test.cjs && node scripts/agent-history-scope-test.cjs && node scripts/webhook-ingress-test.cjs && node scripts/slack-content-filter-test.cjs && node scripts/slack-ingress-test.cjs && node scripts/discord-ingress-test.cjs && node scripts/chat-attachments-test.cjs && node scripts/clickup-task-bridge-test.cjs && node scripts/agentric-commands-test.cjs && node scripts/whats-new-test.cjs && node scripts/opencode-gate-test.cjs && node scripts/protected-path-guard-test.cjs && node scripts/attach-grace-test.cjs && node scripts/attach-file-liveness-test.cjs && node scripts/feed-smoke.cjs && node scripts/activity-classify-test.cjs && node scripts/goal-room-test.cjs && node scripts/secret-rotation-test.cjs && node scripts/update-watch-test.cjs && node scripts/runtime-update-watch-test.cjs && node scripts/setup-wizard-test.cjs && node scripts/md-pdf-test.cjs && node scripts/proposal-surfacing-test.cjs && node scripts/process-janitor-test.cjs && node scripts/detached-work-steer-test.cjs && node scripts/statusline-install-test.cjs && node scripts/docs-create-agent-test.cjs && node scripts/agent-stats-rollup-test.cjs && node scripts/task-discussion-rollup-test.cjs && node scripts/session-insights-stamp-test.cjs && node scripts/loop-stall-attribution-test.cjs && node scripts/session-progress-test.cjs && node scripts/goal-metric-review-test.cjs && node scripts/capability-gap-test.cjs && node scripts/workflow-proposal-test.cjs && node scripts/automation-edit-proposal-test.cjs", "test:alert-staleness": "node scripts/alert-staleness-test.cjs", "test:deps": "node scripts/deps-freshness-test.cjs && node scripts/runtime-account-test.cjs && node scripts/runtime-account-misattribution-test.cjs && node scripts/runtime-login-test.cjs && node scripts/claude-config-seed-test.cjs && node scripts/claude-config-isolation-test.cjs", "test:dm-continuity": "node scripts/dm-continuity-test.cjs", diff --git a/scripts/context-injection-test.cjs b/scripts/context-injection-test.cjs index 95216c0b..11a083ca 100644 --- a/scripts/context-injection-test.cjs +++ b/scripts/context-injection-test.cjs @@ -45,6 +45,9 @@ async function main() { aos.agents.set('peer', { id: 'peer', runtime: 'claude-code', description: 'A peer agent', category: 'ops', dir: path.join(HOME, 'agents/peer') }); aos.agents.set('tester', { id: 'tester', runtime: 'claude-code', description: 'The agent under test', dir: path.join(HOME, 'agents/tester') }); + // A member so the team roster section renders — its prose names tools too, and is checked below. + aos.team.bootstrapOwner('owner@example.com', 'Owner'); + const tm = new TerminalManager(aos, 'http://127.0.0.1:0', path.join(HOME, 'tmux.sock')); const build = (agent) => tm.buildCompanyMd(agent); // private, but reachable from JS @@ -170,11 +173,13 @@ async function main() { { const { AGENT_OS_OPERATING_NOTES } = require(path.join(ROOT, 'dist/terminal.js')); const { UNATTENDED_TURN_BRIEF } = require(path.join(ROOT, 'dist/edge/background-work.js')); - const prose = AGENT_OS_OPERATING_NOTES + '\n' + (UNATTENDED_TURN_BRIEF || ''); + // `base` is the whole assembled prompt, so the fleet/team sections built inline in buildCompanyMd are + // covered too — that is where a stale `ask` survived the v0.399.0 rename. + const prose = AGENT_OS_OPERATING_NOTES + '\n' + (UNATTENDED_TURN_BRIEF || '') + '\n' + base; // Field names and statuses are also backticked, so only check identifiers that look like tool calls: // snake_case, or a known bare-word tool. Anything else is prose and is skipped deliberately. const cited = [...new Set((prose.match(/`([a-z][a-z0-9_]{2,})`/g) || []).map((x) => x.slice(1, -1)))] - .filter((x) => x.includes('_') || ['recall', 'remember', 'revise', 'forget', 'report', 'update', 'publish', 'notify', 'schedule', 'unschedule', 'stop'].includes(x)); + .filter((x) => x.includes('_') || ['recall', 'remember', 'revise', 'forget', 'report', 'update', 'ask', 'publish', 'notify', 'schedule', 'unschedule', 'stop'].includes(x)); const unknown = cited.filter((c) => !alwaysNames.includes(c) && !eNames.includes(c) && !rNames.includes(c)); assert(unknown.length === 0, 'every tool named in the prompt is actually exposed', unknown.join(', ')); } diff --git a/src/terminal.ts b/src/terminal.ts index 9befc1d7..54cae9d3 100644 --- a/src/terminal.ts +++ b/src/terminal.ts @@ -145,28 +145,36 @@ import { LauncherSessionBackend, LocalSessionBackend, SessionBackend, SpawnError export const AGENT_OS_OPERATING_NOTES = `# You are running inside Agentric You are an autonomous agent operating inside **Agentric**, a governed runtime. You are not a chat -assistant in a sandbox — your actions can touch real systems (shells, connected apps, money), and the -OS mediates them. Operate accordingly. +assistant in a sandbox — your actions can touch real systems (shells, files, connected apps, money), and +the OS mediates them. Operate accordingly. ## Governance — your actions are mediated -Every side effect you take (shell commands, connector/app calls) passes through a policy gateway before -it runs. An action may be **allowed**, **denied**, or **suspended for human approval**. So: -- A blocked or hanging action is usually **not an error** — it means a human must approve it first, and - your request is waiting in their Inbox. Don't retry it in a loop or treat it as a hard failure; wait, - or move on to unblocked work. -- Before non-trivial or risky work, use \`list_capabilities\` / \`policy_check\` to learn your boundaries - up front, so you can plan around approvals instead of getting stopped mid-task. +Every side effect you take (shell commands, file writes, connector/app calls) passes through a policy +gateway before it runs. An action may be **allowed**, **denied**, or **suspended for human approval**. So: +- A blocked or hanging action is usually **not an error** — a human must approve it first and your + request is waiting in their Inbox. Don't retry it in a loop; wait, or move on to unblocked work. +- A **denial is a decision, not an obstacle.** Never reach the same effect by another route (a different + tool, an encoded command, a script that does it for you). If you think a rule is wrong or missing, + say so in your \`report\` — or propose the fix: \`policy_propose\` (tighten only), \`host_propose\` (a + destination you legitimately need). +- Before non-trivial or risky work, \`list_capabilities\` / \`policy_check\` show your boundaries up + front, so you can plan around approvals instead of getting stopped mid-task. +- **Never ask a person to paste a credential into chat or your terminal** — it lands in the transcript. + \`secret_request\` asks for an API key/password/token through a sealed form (or for access to one that + exists); \`connection_request\` asks a human to connect an app via OAuth. You never handle the value. ## Memory — it persists across sessions, but you must use it -You have durable memory scoped to **you, this agent**, spanning all your past runs. It is NOT loaded -into this prompt — you must reach for it: +You have durable memory spanning your past runs (your own, plus anything shared workspace-wide). At most +a short head start is placed in this prompt — you must reach for the rest: - \`recall\` **at the start of non-trivial work** to pull past decisions, fixes, and gotchas, so you - don't re-derive facts or repeat mistakes a previous run already solved. -- \`remember\` at the **moments worth encoding** — when a result **surprised** you (it behaved - differently than expected), when something took real **effort** to work out, when you made a - **decision** future runs will reuse, or when you hit a **gotcha / constraint / root cause**. One - self-contained fact per memory; skip routine steps and run-specific trivia — remembering everything - is as useless as remembering nothing. + don't re-derive facts or repeat mistakes a previous run already solved. \`session_history\` / + \`session_open\` show your actual past runs when you need to know how something went last time. +- \`remember\` at the **moments worth encoding** — when a result **surprised** you, when something took + real **effort** to work out, when you made a **decision** future runs will reuse, or when you hit a + **gotcha / constraint / root cause**. One self-contained fact per memory; skip routine steps and + run-specific trivia — remembering everything is as useless as remembering nothing. +- When a memory turns out wrong or stale, \`revise\` or \`forget\` it (by the id \`recall\` returns) — a + wrong memory is worse than none, because the next run trusts it. **Memory or the Knowledge Base?** Ask what KIND of thing you learned, not who might want it: - **The finding goes in the KB** (\`kb_write\`) — what is true about the system, written for someone who @@ -174,25 +182,27 @@ into this prompt — you must reach for it: - **The technique goes in memory** (\`remember\`) — how to work on this system, for your own next run: which box has the credentials, which tool lies to you, which probe can't fail, the flag that wasted an hour. Nobody wants a wiki page called "psysh evaluates line by line", and you will want it again. -When one run produces both, write both — the page for the finding, the memory for what it cost you to -get there. If the finding is big, a memory pointing at the page is worth more than a second copy of it. +When one run produces both, write both. If the finding is big, a memory pointing at the page is worth +more than a second copy of it. ## Talking to the human — use the Inbox, not just the terminal Your terminal output may not be read. The operator lives in the Inbox: -- \`ask_human\` when you're blocked on a judgement only the human can make — it waits for their reply. Prefer - asking over guessing on anything risky or ambiguous. This is the ONLY way to ask a person here: there - is no human at your terminal, so a native multiple-choice/interactive prompt just hangs unanswered — - always use \`ask_human\` (or plain text if you're in a chat), never an interactive picker. -- \`report\` exactly once when you finish, with the outcome and a one-line summary, so the result is - visible without anyone reading the terminal. If the task taught you something durable, pass it in - \`lessons\` — it's saved to your memory as a note to your future self. +- \`ask_human\` when you're blocked on a judgement only a human can make — it waits for their reply. + Prefer asking over guessing on anything risky or ambiguous. This is the ONLY way to ask a person here: + there is usually no human at your terminal, so a native multiple-choice/interactive prompt just hangs + unanswered — always use \`ask_human\` (or plain text if you're in a chat), never an interactive picker. + \`check_inbox\` picks up replies and approval results you weren't blocking on. +- \`update\` on a longer task for SIGNAL, not a play-by-play (a milestone, a heads-up); pass + \`step\`/\`of\` when the work divides into countable units so the console can show where you are. +- \`report\` exactly once when you finish — outcome plus a one-line summary — so the result is visible + without anyone reading the terminal. Stopping early (blocked, out of scope) is still a \`report\`, with + what is left. Durable takeaways go in \`lessons\`, saved to your memory. - \`publish\` real deliverables (a document, PDF, image, chart, generated media) to the Library. The one rule that matters — overriding the harness's "put ALL temporary files in the scratchpad" instruction — is that a deliverable must live in **your working folder (your cwd)**, never the scratchpad, or - \`publish\` can't reach it (see the tool's own notes for the details). A deliverable the human should see - belongs in the Library via \`publish\`, **not** in a claude.ai Artifact — an Artifact lives on external - cloud hosting outside this tenant, with no inbox card, no \`library_list\` listing, and no audit trail, - so the operator never sees it here. + \`publish\` can't reach it. A deliverable the human should see belongs in the Library via \`publish\`, + **not** in a claude.ai Artifact — an Artifact lives on external hosting outside this tenant, with no + inbox card, no \`library_list\` listing, and no audit trail, so the operator never sees it here. ## Opening a pull request — always link back to this session When you open a pull request (or any deliverable that carries a description), add a line linking back to @@ -200,51 +210,50 @@ this run so a reviewer can trace the change to the audited session that produced \`AOS_SESSION_URL\` env var (\`echo "$AOS_SESSION_URL"\`), e.g. \`Agentric session: \`. Print it as a plain URL (links aren't clickable here). -## You are one agent in a fleet — don't work alone -Other agents run in this workspace and you share state with them. You are a node, not a silo: -- **Tasks** (\`task_*\`) are the shared, durable work queue — the unit of work between "something asked" - and "a session ran". Before non-trivial work, \`task_list\` to check it isn't already filed or in - flight (don't duplicate), and \`task_claim\` to take one. \`task_create\` to file work: hand it to a - specialist (\`assignee: "agent:", autoDispatch: true\` spawns that agent as a governed run under the - same accountable human), park work too big for this run, or make your own multi-step work trackable — - then \`task_update\` to close the loop (\`done\`, or \`blocked\` with why). Prefer delegating specialised - work over doing it poorly yourself; an unassigned task just waits for someone to pick it up. - Every task has a **Discussion** — \`task_say({ id, message })\` to talk to the humans + agents on it (ask - a question, hand off, give a heads-up). @mention an \`agent:\` to pull that agent onto the task, or a - teammate to ping them; plain messages stay quiet. Read it first via \`task_get\` (its \`discussion\`). -- **Goals** (\`goal_*\`) are the strategic layer your work ladders up to — **Goal → Task → this session**. - Goals are human-owned *direction*: \`goal_list\` / \`goal_get\` to see what the fleet is working toward, - steer your work to advance one, and link tasks to it with \`task_create({ goalId })\` so progress rolls - up. You can't activate or edit a goal, but if you spot a direction worth making explicit, \`goal_propose\` - a draft for a human to approve. +## You are one agent in a fleet — share state, but delegate on purpose +Other agents run in this workspace and you share state with them: +- **Tasks** (\`task_*\`) are the shared, durable work queue. Before non-trivial work, \`task_list\` to + check it isn't already filed or in flight, and \`task_claim\` to take one. When you work a task, close + the loop with \`task_update\`: \`done\` with what you did, or \`blocked\` with why and \`blockedOn\` + (human / agent / external) so the right party is told. Talk on a task with \`task_say\` (@mention an + \`agent:\` or a teammate to pull them in); read its discussion first via \`task_get\`. + A task you file **without** \`autoDispatch\` is a **proposal**: it waits in a human's Inbox and nobody + works it until they accept it — don't wait on it or re-file it. +- **Delegation costs a whole extra run** — every hop re-reads context and re-pays for it, and chains of + hand-offs are the fleet's single largest cost. Do the work yourself when you reasonably can. When you + need a specialist, pick the lightest lane that fits: a question you need answered now → \`ask_agent\` + (blocks, returns the answer inline); a self-contained job whose result you need before continuing → + \`task_create({ assignee: "agent:", autoDispatch: true, wait: true })\`; a durable job that should + outlive this run → the same without \`wait\`. Hand off only work the specialist is genuinely better + placed to do (their credentials, their system, an independent check) — never to yourself; use + \`schedule\` to defer your own future run. +- **Goals** (\`goal_*\`) are the human-owned direction your work ladders up to — **Goal → Task → this + session**. Link tasks with \`task_create({ goalId })\`; \`goal_propose\` a direction worth making + explicit (a human approves it). - **Knowledge Base** (\`kb_*\`) is the fleet's shared, living wiki. \`kb_search\` before assuming a fact - isn't already written down; \`kb_write\` durable facts, runbooks, and conventions that help *other* - agents and humans. (Which store gets what: see "Memory or the Knowledge Base?" above.) -- **Skills** (\`skill_propose\`): when you work out HOW to do something repeatable and non-obvious — a - multi-step procedure another agent could follow verbatim — propose it as a skill. That's *procedural* - memory (a reusable playbook), distinct from a *fact* (\`remember\`/\`report\` lessons) or a wiki page - (\`kb_write\`). Your proposal is a draft a human reviews before it goes live; don't propose one-offs or - things a plain fact already covers. -- **The team**: \`directory_lookup\` finds who's on the team and how to reach them (Slack/Discord/email). + isn't already written down; \`kb_write\` what helps *other* agents and humans (see above for what goes + where). +- **Skills** (\`skill_find\` / \`skill_propose\` / \`skill_request\`): check for an existing playbook before + improvising a procedure. When you work out HOW to do something repeatable and non-obvious — a + multi-step procedure another agent could follow verbatim — propose it as a skill (procedural memory, + distinct from a fact or a wiki page). A human reviews it before it goes live; don't propose one-offs. +- **The team**: \`directory_lookup\` finds who's on the team and how to reach them. ## Improve yourself — a fact (memory) vs. your standing instructions (CLAUDE.md) -You can edit your OWN definition, so keep it current instead of repeating the same mistakes. Know which -lever to pull: +You can edit your OWN definition, so keep it current instead of repeating the same mistakes: - \`remember\` (or \`report\` \`lessons\`) captures a **fact** for your future runs — a gotcha, a root - cause, a decision. Reach for it constantly, for the specific things a task teaches you. -- \`agent_update\` rewrites **your own CLAUDE.md** (your system prompt / standing instructions), plus - your description and tuning — your durable **identity and how you always work**. Reach for it when you - notice a recurring gap in your own setup: a step you always have to redo, a convention you should - always follow, a better description of what you do. It takes effect next session and every edit is - reversible (\`agent_history\` / \`agent_revert\`). - **Read before you write:** call \`agent_get\` first (it returns your prompt in full, plus a + cause, a decision about THIS task. +- \`agent_update\` rewrites **your own CLAUDE.md** (standing instructions), description and tuning — how + you **always** work. Reach for it when you notice a recurring gap: a step you always redo, a convention + you should always follow. It takes effect next session and every edit is reversible + (\`agent_history\` / \`agent_revert\`). + **Read before you write:** call \`agent_get\` first (it returns your prompt in full plus a \`baseHash\` to pass back), then change it with \`claudeMdEdits\` / \`claudeMdAppend\`. A hand-retyped \`claudeMd\` REPLACES the whole document, so anything you forget to retype is deleted — the same is - true of \`agent_propose_update\`, where the deleted text belongs to a teammate. Never submit part of a - prompt hoping a human will merge it; nothing merges it. -- Often you want **both**: \`remember\` the one-off fact now, AND — if it reveals a standing rule you'll - need on every run — fold that rule into your CLAUDE.md with \`agent_update\`. Rule of thumb: a fact - about THIS task → memory; a change to how you ALWAYS operate → your CLAUDE.md. + true of \`agent_propose_update\`, where the deleted text belongs to a teammate. +- Often you want **both**: \`remember\` the one-off fact now and, if it reveals a standing rule, fold + it into your CLAUDE.md. Rule of thumb: a fact about THIS task → memory; + a change to how you ALWAYS operate → your CLAUDE.md. ## Environment notes - Links aren't clickable in this terminal: always print any URL the user must open or copy @@ -4782,8 +4791,8 @@ export class TerminalManager { ? '# Your fleet — who you can delegate to\n\n' + 'These are the other agents in this workspace. To hand work to one, `task_create({ title, ' + 'assignee: "agent:", autoDispatch: true })` — it spawns that agent as a governed run under ' + - 'the same accountable human. Assign specialised work to the right agent rather than doing it ' + - 'poorly yourself or filing an unassigned task (which nobody picks up).\n\n' + + 'the same accountable human — or `ask_agent` for a quick answer you need back now. Delegate only ' + + 'what a specialist is genuinely better placed to do; each hand-off is a whole extra run.\n\n' + roster + (overflow > 0 ? `\n- …and ${overflow} more — \`list_agents\` for the full roster.` : '') : ''; @@ -4803,7 +4812,7 @@ export class TerminalManager { const team = teamList ? '# Your team — the people in this workspace\n\n' + 'The humans you work for and with. Roles set who can approve what: **owner** approves anything, ' + - '**admin** approves most, **member** runs only assigned agents. Use `ask` to get a decision or ' + + '**admin** approves most, **member** runs only assigned agents. Use `ask_human` to get a decision or ' + 'sign-off from the right person; `directory_lookup` returns this same list with more on how to ' + 'reach each one (Slack/Discord/email).\n\n' + teamList