codemode rip, part 2: the agent loop runs on itx#1446
Conversation
185a081 to
947173d
Compare
Bugbot findings: (#1446 High) the agent loop shipped without the slack cap, breaking Slack bang commands and LLM replies at this point in the stack — the slack (full guidance text, including the quiet-reply rule and the Promise.all acknowledgment pattern, addressing the #1447 Medium) and agents caps move down from part 3 to where the loop lands, with the SlackCapability call() adapter and allowlist entries. (#1447 High at its source) ensureItxContext seeding is now versioned: bump AGENT_CONTEXT_CAPS_VERSION and existing agents re-define caps on next wake (defines upsert; capability-noted idempotency keys dedupe). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
e173b4f to
bdda255
Compare
|
Bugbot High addressed in bdda255 — and it was a fair catch of bad stacking on my part: the |
947173d to
ee96873
Compare
Bugbot findings: (#1446 High) the agent loop shipped without the slack cap, breaking Slack bang commands and LLM replies at this point in the stack — the slack (full guidance text, including the quiet-reply rule and the Promise.all acknowledgment pattern, addressing the #1447 Medium) and agents caps move down from part 3 to where the loop lands, with the SlackCapability call() adapter and allowlist entries. (#1447 High at its source) ensureItxContext seeding is now versioned: bump AGENT_CONTEXT_CAPS_VERSION and existing agents re-define caps on next wake (defines upsert; capability-noted idempotency keys dedupe). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
bdda255 to
68e6d30
Compare
8a172a0 to
071375e
Compare
The agent's execution engine is now the itx runner; the CodemodeSession DO is no longer in the loop: - Agent DO: ensureCodemodeSession → ensureItxContext. Each agent gets a child context (ctx_…) seeded with its tools as caps: chat + debug via the new AgentToolsCapability loopback forwarder (DO names derive from registry-injected projectId — a definer can only reach agents in the context's own project), plus ai / os / gmail. One agent/capability-noted event per cap lands on the agent stream so the LLM keeps learning its tools from history. - Agent-host processor: LLM code fences run DETACHED through runItxScript (record on the agent stream; the completed event is the durable trace); itx/execution-completed turns into agent input (yaml block now includes console logs). LLM scripts stay written as `async (ctx) => …` — ctx IS the itx handle, names line up. - Enqueued executions: itx/execution-requested with `enqueued: true` is a queue entry the agent-host runs (runItxScript gains executionId + recordRequested params) — Slack bang commands use this. - Slack-agent processor: thread-route etiquette becomes a capability-noted event; status side effects key on itx/execution-*; the event-mediated ctx.slack.agent.threadInfo() tool is DROPPED for now (the webhook payload carries channel/thread_ts; restore later as a dialable cap if missed). - Agent processor: consumes agent/capability-noted instead of codemode/tool-provider-registered; rendering and event-type explanation updated; contracts drop the codemode dep. Tests updated to the new events; threadInfo test removed with the feature. Part 3 deletes the codemode domain itself. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Bugbot findings: (#1446 High) the agent loop shipped without the slack cap, breaking Slack bang commands and LLM replies at this point in the stack — the slack (full guidance text, including the quiet-reply rule and the Promise.all acknowledgment pattern, addressing the #1447 Medium) and agents caps move down from part 3 to where the loop lands, with the SlackCapability call() adapter and allowlist entries. (#1447 High at its source) ensureItxContext seeding is now versioned: bump AGENT_CONTEXT_CAPS_VERSION and existing agents re-define caps on next wake (defines upsert; capability-noted idempotency keys dedupe). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
68d00ca to
7b6c9e2
Compare
…te; knip) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 5b92858. Configure here.
| invocation: { kind: "event" }, | ||
| name: "slack", | ||
| instructions: | ||
| "Use ctx.slack.agent.threadInfo() only when you need route context that is not already in the Slack webhook payload. Slack agents MUST respond on the same thread_ts that received the message; otherwise they will not receive responses from that thread. Unless explicitly required, always include thread_ts in Slack replies. Do not post to Slack unless the bot was explicitly mentioned, a user directly asks or instructs you, or the surrounding thread context clearly calls for agent action. Normal Slack replies can use channel/thread_ts from the webhook event directly.", |
There was a problem hiding this comment.
Duplicate Slack capability notes
Medium Severity
Slack-backed agents now get two agent/capability-noted events for the same slack tool: one from ensureItxContext (full API and Promise.all guidance) and another when thread route is configured (shorter etiquette text). The agent processor renders both into model context with conflicting instructions.
Additional Locations (2)
Reviewed by Cursor Bugbot for commit 5b92858. Configure here.
| }); | ||
| await this.ctx.storage.put("itxContextId", contextId); | ||
| await this.ctx.storage.put("itxContextCapsVersion", AGENT_CONTEXT_CAPS_VERSION); | ||
| return contextId; |
There was a problem hiding this comment.
Concurrent itx context seeding
Medium Severity
ensureItxContext is not serialized. Overlapping calls (e.g. multiple detached runAgentItxScript runs via getItxContextId before storage writes finish) can each mint a new ctx id, define caps on different contexts, and race on itxContextId persistence.
Reviewed by Cursor Bugbot for commit 5b92858. Configure here.
Stacked on #1446. The codemode domain is deleted — net **-8.3k lines**. ## What went where - **`CodemodeSession` DO → tombstone.** The class + `CODEMODE_SESSION` binding deliberately keep existing: production streams carry durable callable subscribers that dial the namespace by name, and a vanished class is exactly the 2026-06-10 legacy-subscriber outage. The tombstone accepts `requestStreamSubscription` dials and no-ops (with a warning log). Proper removal = follow-up with a DO deletion migration + stream subscriber cleanup, after this soaks. - **`AiCapability` / `OrpcCapability`** → `src/rpc-targets/os-capabilities.ts` (they're itx caps now, not codemode examples). - **`ExecuteCodemodeFunctionCallInput`** → `src/rpc-targets/legacy-codemode-call.ts`; capability entrypoints keep the legacy method while callers migrate to `call({ path, args })`. `SlackCapability` gains a real `call()`. - **Agent contexts gain `slack` + `agents` caps** (SlackCapability path-call with the old etiquette instructions, AgentCapability members for pipelined subagents) — restoring the full pre-itx provider surface. - **Per-context workspaces**: `ctx.workspace` on a child context now maps to workspace `itx:<contextId>` (derived identically in `handle.ts` and the agent's workspace prep). Existing agents re-clone iterate-config once into the new workspace id. - **UI/oRPC**: `project.codemode` contract + router, codemode-sessions routes, session controls, and the new-agent tool-provider compiler are deleted — the Agent DO seeds caps (and the LLM-visible capability notes) on wake, so the form stops compiling registration events. - slack-integration bootstrap stops subscribing codemode to routed streams. ## Test changes - Deleted: codemode e2e suites, `codemode-builder`, and `e2e-test-map.e2e.test.ts` (built entirely on the codemode fixture; the itx e2e suite covers the replacement model). - `agents.e2e` converted to itx events. Coverage honestly lost with the per-call event mechanism: function-call-level assertions (workspace op sequence, slack-call payload echo, debug-output sanitization) — those now verify via generated code + execution-completed `ok` + the real side effects. - Unit: 205 passing; repo-wide typecheck/lint/format green. ## Follow-ups (noted in itx-next.md territory) - prd/preview cleanup: tombstone soak → DO deletion migration + subscriber-event cleanup. - `executeCodemodeFunctionCall` legacy methods on capability entrypoints → delete once nothing dials them. - `packages/shared/src/codemode/*` (json-schema type generation) still used by OrpcCapability's listProcedures — rename/move later. 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **High Risk** > Large removal of script execution, providers, and oRPC routes touches agent/Slack flows and production stream subscribers; behavior changes until tombstone subscribers are cleaned up. > > **Overview** > **Removes the codemode domain** (~8k lines): the `CodemodeSession` DO implementation, stream processor, default/example providers, UI session controls, and the entire **`project.codemode` oRPC surface** (sessions, `executeScript`, `streamEvents`, `describe`). > > **`CodemodeSession` becomes a tombstone** — same class/binding so existing stream callable subscribers keep dialing without outage; `requestStreamSubscription` no-ops with a warning until subscriber cleanup lands. > > **Agents run on itx instead of codemode events:** script runs use `runItxScript` with `convention: "ctx"` and direct LLM code; workspaces are **`itx:<contextId>`** (aligned with the itx handle), with single-flight `ensureItxContext`. Capability types move to **`rpc-targets/legacy-codemode-call`** and **`os-capabilities`**; tests/assertions shift from `codemode/*` and per-call function events to **`itx/execution-*`** and **`agent/capability-noted`**. > > **E2E:** codemode suites, `CodemodeBuilder`, and `e2e-test-map` are deleted; `agents.e2e` is updated for itx (some granular function-call assertions dropped). > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 24365a0. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> <!-- CLOUDFLARE_PREVIEW --> ## Environment Config Lease <!-- CLOUDFLARE_PREVIEW_STATE --> <!-- { "apps": { "os": { "appDisplayName": "OS", "appSlug": "os", "status": "tests-failed", "updatedAt": "2026-06-10T15:05:24.078Z", "headSha": "9dd5fb619c994aadf847645bf0c6d7ee4f1aa7c1", "message": "...(truncated)\ns\nAssertionError: expected 'Error' to be 'ItxError' // Object.is equality\n\nExpected: \"ItxError\"\nReceived: \"Error\"\n\n ❯ src/itx/e2e/itx.e2e.test.ts:397:23\n 395| );\n 396| expect(error).not.toBeNull();\n 397| expect(error!.name).toBe(\"ItxError\");\n | ^\n 398| expect(error!.code).toBe(\"NOT_FOUND\");\n 399| expect(error!.details).toEqual({ projectIdOrSlug: \"definitely-not-a-…\n\n⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯\n\n\n\n> @iterate-com/os@0.0.1 e2e /home/runner/work/iterate/iterate/apps/os\n> vitest --config e2e/vitest.config.ts -t 'OS preview smoke'\n\n[vitest-artifacts] run root: /tmp/os-e2e-OV4oT8\n[vitest] run slug: os-vitest-run-20260610-150101\n\n RUN v4.0.15 /home/runner/work/iterate/iterate/apps/os\n\nstdout | e2e/vitest/preview-smoke.e2e.test.ts > OS preview smoke\nOS preview smoke passed for https://os.iterate-preview-9.com/\n\n ✓ e2e/vitest/preview-smoke.e2e.test.ts (1 test) 6957ms\n ✓ OS preview smoke 6956ms\n ↓ e2e/vitest/admin-project.e2e.test.ts (1 test | 1 skipped)\n ↓ e2e/vitest/agents.e2e.test.ts (7 tests | 7 skipped)\n\n Test Files 1 passed | 2 skipped (3)\n Tests 1 passed | 8 skipped (9)\n Start at 15:01:01\n Duration 7.56s (transform 142ms, setup 0ms, import 348ms, tests 6.96s, environment 0ms)\n\n\n> @iterate-com/os@0.0.1 e2e:itx /home/runner/work/iterate/iterate/apps/os\n> vitest run --config src/itx/e2e/vitest.config.ts --project node\n\n[vitest-artifacts] run root: /tmp/os-itx-e2e-5Kcek5\n[vitest] run slug: os-vitest-run-20260610-150109\n\n RUN v4.0.15 /home/runner/work/iterate/iterate/apps/os\n\n ❯ node src/itx/e2e/itx.e2e.test.ts (10 tests | 1 failed | 1 skipped) 99422ms\n ✓ itx scripts run identically over Cap'n Web and /api/itx/run 13584ms\n ✓ the five-step capability flow: provide live, call, promote durable, call from a script 13702ms\n ✓ platform bindings are dialable capabilities (raw + wrapped) 11602ms\n ↓ the first-party McpClient cap bridges a remote MCP server\n ✓ script executions leave a two-event record on the /itx stream 13149ms\n ✓ worker caps hold a correctly scoped itx of their own 13039ms\n ✓ members caps auto-proxy every public method/getter at any depth 9466ms\n ✓ one dynamic worker cap calls another's methods through its own itx 9256ms\n × kernel errors cross capnweb as ItxError-shaped errors with codes 1572ms\n ✓ revoked and offline caps fail with instructive errors 10686ms\n ✓ node src/itx/e2e/itx-fork.e2e.test.ts (3 tests) 66888ms\n ✓ fork: child caps shadow the parent, misses delegate up the chain 15899ms\n ✓ fork narrows access: a session cannot reach sibling projects 23563ms\n ✓ fork: child worker caps run with the owning project's authority 24677ms\n ✓ node src/itx/e2e/itx-egress.e2e.test.ts (3 tests) 39982ms\n ✓ itx.fetch substitutes secrets through project egress (explicit door) 10155ms\n ✓ bare fetch() in a project itx script goes through egress (implicit door) 14358ms\n ✓ bare fetch() inside a worker cap goes through egress (implicit door) 13693ms\n ✓ node src/itx/e2e/itx-http.e2e.test.ts (2 tests) 33070ms\n ✓ facet caps keep private durable state across invocations 9914ms\n ✓ HTTP-exposed caps serve their own hostname: admin, share URL, public 20529ms\n ✓ node src/itx/e2e/itx-subscribe.e2e.test.ts (1 test) 14363ms\n ✓ subscribe replays history, tails live appends, and unsubscribes 12306ms\n\n Test Files 1 failed | 4 passed (5)\n Tests 1 failed | 17 passed | 1 skipped (19)\n Start at 15:01:09\n Duration 254.34s (transform 80ms, setup 0ms, import 187ms, tests 253.72s, environment 0ms)\n\n\n::error file=/home/runner/work/iterate/iterate/apps/os/src/itx/e2e/itx.e2e.test.ts,title=[node] src/itx/e2e/itx.e2e.test.ts > kernel errors cross capnweb as ItxError-shaped errors with codes,line=397,column=23::AssertionError: expected 'Error' to be 'ItxError' // Object.is equality%0A%0AExpected: \"ItxError\"%0AReceived: \"Error\"%0A%0A ❯ src/itx/e2e/itx.e2e.test.ts:397:23%0A%0A\n ELIFECYCLE Command failed with exit code 1.", "publicUrl": "https://os.iterate-preview-9.com", "runUrl": "https://github.com/iterate/iterate/actions/runs/27284870355", "shortSha": "9dd5fb6" }, "semaphore": { "appDisplayName": "Semaphore", "appSlug": "semaphore", "status": "deployed", "updatedAt": "2026-06-10T14:56:06.306Z", "headSha": "9dd5fb619c994aadf847645bf0c6d7ee4f1aa7c1", "message": null, "publicUrl": "https://semaphore.iterate-preview-9.com", "runUrl": "https://github.com/iterate/iterate/actions/runs/27284870355", "shortSha": "9dd5fb6" } }, "environmentConfigLease": { "dopplerConfig": "preview_9", "leasedUntil": 1781109314547, "leaseId": "eee2cb43-98d1-4d7e-b76a-9508a07fcfc1", "slug": "preview-9", "type": "environment-config-lease" } } --> <!-- /CLOUDFLARE_PREVIEW_STATE --> Lease: `preview-9` Doppler config: `preview_9` Type: `environment-config-lease` Leased until: 2026-06-10T16:35:14.547Z ### OS Status: tests failed Commit: `9dd5fb6` Preview: https://os.iterate-preview-9.com Summary: AssertionError: expected 'Error' to be 'ItxError' // Object.is equality [Workflow run](https://github.com/iterate/iterate/actions/runs/27284870355) Updated: 2026-06-10T15:05:24.078Z <details> <summary>Failure details</summary> <pre>...(truncated) s AssertionError: expected 'Error' to be 'ItxError' // Object.is equality Expected: "ItxError" Received: "Error" ❯ src/itx/e2e/itx.e2e.test.ts:397:23 395| ); 396| expect(error).not.toBeNull(); 397| expect(error!.name).toBe("ItxError"); | ^ 398| expect(error!.code).toBe("NOT_FOUND"); 399| expect(error!.details).toEqual({ projectIdOrSlug: "definitely-not-a-… ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯ > @iterate-com/os@0.0.1 e2e /home/runner/work/iterate/iterate/apps/os > vitest --config e2e/vitest.config.ts -t 'OS preview smoke' [vitest-artifacts] run root: /tmp/os-e2e-OV4oT8 [vitest] run slug: os-vitest-run-20260610-150101 RUN v4.0.15 /home/runner/work/iterate/iterate/apps/os stdout | e2e/vitest/preview-smoke.e2e.test.ts > OS preview smoke OS preview smoke passed for https://os.iterate-preview-9.com/ ✓ e2e/vitest/preview-smoke.e2e.test.ts (1 test) 6957ms ✓ OS preview smoke 6956ms ↓ e2e/vitest/admin-project.e2e.test.ts (1 test | 1 skipped) ↓ e2e/vitest/agents.e2e.test.ts (7 tests | 7 skipped) Test Files 1 passed | 2 skipped (3) Tests 1 passed | 8 skipped (9) Start at 15:01:01 Duration 7.56s (transform 142ms, setup 0ms, import 348ms, tests 6.96s, environment 0ms) > @iterate-com/os@0.0.1 e2e:itx /home/runner/work/iterate/iterate/apps/os > vitest run --config src/itx/e2e/vitest.config.ts --project node [vitest-artifacts] run root: /tmp/os-itx-e2e-5Kcek5 [vitest] run slug: os-vitest-run-20260610-150109 RUN v4.0.15 /home/runner/work/iterate/iterate/apps/os ❯ node src/itx/e2e/itx.e2e.test.ts (10 tests | 1 failed | 1 skipped) 99422ms ✓ itx scripts run identically over Cap'n Web and /api/itx/run 13584ms ✓ the five-step capability flow: provide live, call, promote durable, call from a script 13702ms ✓ platform bindings are dialable capabilities (raw + wrapped) 11602ms ↓ the first-party McpClient cap bridges a remote MCP server ✓ script executions leave a two-event record on the /itx stream 13149ms ✓ worker caps hold a correctly scoped itx of their own 13039ms ✓ members caps auto-proxy every public method/getter at any depth 9466ms ✓ one dynamic worker cap calls another's methods through its own itx 9256ms × kernel errors cross capnweb as ItxError-shaped errors with codes 1572ms ✓ revoked and offline caps fail with instructive errors 10686ms ✓ node src/itx/e2e/itx-fork.e2e.test.ts (3 tests) 66888ms ✓ fork: child caps shadow the parent, misses delegate up the chain 15899ms ✓ fork narrows access: a session cannot reach sibling projects 23563ms ✓ fork: child worker caps run with the owning project's authority 24677ms ✓ node src/itx/e2e/itx-egress.e2e.test.ts (3 tests) 39982ms ✓ itx.fetch substitutes secrets through project egress (explicit door) 10155ms ✓ bare fetch() in a project itx script goes through egress (implicit door) 14358ms ✓ bare fetch() inside a worker cap goes through egress (implicit door) 13693ms ✓ node src/itx/e2e/itx-http.e2e.test.ts (2 tests) 33070ms ✓ facet caps keep private durable state across invocations 9914ms ✓ HTTP-exposed caps serve their own hostname: admin, share URL, public 20529ms ✓ node src/itx/e2e/itx-subscribe.e2e.test.ts (1 test) 14363ms ✓ subscribe replays history, tails live appends, and unsubscribes 12306ms Test Files 1 failed | 4 passed (5) Tests 1 failed | 17 passed | 1 skipped (19) Start at 15:01:09 Duration 254.34s (transform 80ms, setup 0ms, import 187ms, tests 253.72s, environment 0ms) ::error file=/home/runner/work/iterate/iterate/apps/os/src/itx/e2e/itx.e2e.test.ts,title=[node] src/itx/e2e/itx.e2e.test.ts > kernel errors cross capnweb as ItxError-shaped errors with codes,line=397,column=23::AssertionError: expected 'Error' to be 'ItxError' // Object.is equality%0A%0AExpected: "ItxError"%0AReceived: "Error"%0A%0A ❯ src/itx/e2e/itx.e2e.test.ts:397:23%0A%0A ELIFECYCLE Command failed with exit code 1.</pre> </details> ### Semaphore Status: deployed Commit: `9dd5fb6` Preview: https://semaphore.iterate-preview-9.com [Workflow run](https://github.com/iterate/iterate/actions/runs/27284870355) Updated: 2026-06-10T14:56:06.306Z <!-- /CLOUDFLARE_PREVIEW --> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Final follow-up to the codemode rip (#1445/#1446/#1447). MCP's streamable HTTP transport is a stateless protocol — fetch with metadata — so nothing about an MCP client belongs in a Durable Object. ## What - **`OutboundMcpFromOurClientCapability` DO deleted** — class, worker export, alchemy namespace + `OUTBOUND_MCP_FROM_OUR_CLIENT_CAPABILITY` binding, vitest harness wiring. Nothing has dialed it since the codemode rip (its only caller was the deleted provider registration). - **Core helpers promoted** to `src/itx/caps/mcp-client-core.ts` with clean names: `connectMcp` (custom-fetch aware, closes on failed connect), `listMcpTools`, `executeMcpToolCall`. `McpClient` dedupes onto them; the mock-server unit test moved and adapted. - **The DO allusion is gone from the docs**: `McpClient`'s header now states statelessness as the design ("connect → call → close, per invocation; deliberately no Durable Object anywhere in this path") instead of presenting connection caching as a future optimization. ## Deploy note This is the repo's first Durable Object class deletion. The DO had no SQLite (in-memory cache only) and no inbound subscribers, so deletion is data-safe; alchemy is expected to emit the `deleted_classes` migration on deploy — **this PR's preview deploy is the proof**. If it refuses, the fallback is a tombstone class like `CodemodeSession`'s. ## Testing Repo typecheck / lint / knip / unit suite green locally (incl. the moved mock-server core test). The `McpClient` e2e remains gated on a reachable MCP server. 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- CLOUDFLARE_PREVIEW --> ## Environment Config Lease <!-- CLOUDFLARE_PREVIEW_STATE --> <!-- { "apps": {}, "environmentConfigLease": { "dopplerConfig": "preview_4", "leasedUntil": 1781109925654, "leaseId": "f7427e44-72e2-4e04-8617-122e174b3c57", "slug": "preview-4", "type": "environment-config-lease" } } --> <!-- /CLOUDFLARE_PREVIEW_STATE --> Lease: `preview-4` Doppler config: `preview_4` Type: `environment-config-lease` Leased until: 2026-06-10T16:45:25.654Z <!-- /CLOUDFLARE_PREVIEW --> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>


Stacked on #1445. The agent's execution engine moves from CodemodeSession to the itx runner.
What
ctx_…) seeded with its tools as caps:chat+debugvia a newAgentToolsCapabilityloopback forwarder, plusai/os/gmail. Oneagent/capability-notedevent per cap lands on the agent stream, so the LLM keeps learning its tools from stream history exactly as before (the agent processor renders these into model-visible context).runItxScript, detached — the two-event execution record on the agent stream is the durable trace, anditx/execution-completedturns into agent input (the yaml block now includes console output). LLM scripts stay written asasync (ctx) => …:ctxIS the itx handle —ctx.chat,ctx.ai,ctx.os,ctx.gmail,ctx.fetchall line up name-for-name.itx/execution-requestedwithenqueued: trueis a queue entry the agent-host runs (first taste of processor mode from itx-next §4). Slack bang commands use this path.AgentToolsCapabilityderives the agent DO name from registry-injectedprojectId+ definer'sagentPath— a raw durable-object ref would have let a definer address another project's agent by name.Behavior changes
ctx.slack.agent.threadInfo()is dropped (it was an event-mediated tool, a codemode-only mechanism). The webhook payload already carries channel/thread_ts — the old instructions said as much — and it can return as a dialable cap (SlackAgentToolsCapability) if missed.Testing
typecheck / lint / format green; unit suite updated to the new events (207 passing). Needs a deployed e2e pass for the agent loop — the existing agents e2e suite covers it once this stack deploys to a preview.
🤖 Generated with Claude Code
Note
High Risk
Touches core agent execution, tool dialing, and Slack paths; detached itx runs lack codemode-style retry on DO restart, and security relies on registry-injected projectId in AgentToolsCapability.
Overview
Replaces CodemodeSession with an itx child context per agent: tools are registered as caps (
chat/debugvia newAgentToolsCapability, plusai,os,gmail,slack,agents), andagent/capability-notedevents on the agent stream replacecodemode/tool-provider-registeredfor LLM-visible tool docs.Agent-host runs LLM code fences through
runItxScript(detached) and mapsitx/execution-completedback to agent input (including console logs). Slack bang commands enqueueitx/execution-requestedwithenqueued: true.SlackCapabilitygains an itxcallpath;ctx.slack.agent.threadInfoand codemode function-call events are removed.runItxScriptaccepts optionalexecutionIdandrecordRequested: falsewhen the queue entry already exists.Reviewed by Cursor Bugbot for commit 5b92858. Bugbot is set up for automated code reviews on this repo. Configure here.
Environment Config Lease
No active environment config lease.
OS
Status: released
Commit:
5b92858Preview: https://os.iterate-preview-4.com
Summary: Preview app released.
Workflow run
Updated: 2026-06-10T14:51:38.665Z
Semaphore
Status: released
Commit:
7b6c9e2Preview: https://semaphore.iterate-preview-4.com
Summary: Preview app released.
Workflow run
Updated: 2026-06-10T14:51:28.574Z