Skip to content

Seed agent processor registration events#1371

Closed
jonastemplestein wants to merge 1 commit into
mainfrom
codex/seed-agent-processor-registration
Closed

Seed agent processor registration events#1371
jonastemplestein wants to merge 1 commit into
mainfrom
codex/seed-agent-processor-registration

Conversation

@jonastemplestein

@jonastemplestein jonastemplestein commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Follow-up to #1370.\n\nSeeds the standard shared processor registration events in the initial new-agent append batch, immediately after subscription configuration and before tool-provider registrations. This removes the visible raw-stream gap where the first processor registration only appears after the runner cold-start/replay path.\n\nProduction diagnosis showed the remaining ~1.2-2.1s floor is present even for subscriptions-only streams, so the underlying cost is Stream DO -> StreamProcessorRunner DO WebSocket/RPC startup rather than agent context rendering. This patch does not remove that platform/protocol floor; it removes the registration marker from that delayed path and saves the first registration append per shared processor.\n\nValidation:\n- pnpm --dir apps/os typecheck\n- pnpm --dir apps/os test\n- pnpm exec oxlint . --threads 1 --deny-warnings\n- pnpm format:check

Environment Config Lease

No active environment config lease.

OS

Status: released
Commit: 366d125
Preview: https://os.iterate-preview-3.com
Summary: Preview app released.
Workflow run
Updated: 2026-06-05T14:52:58.706Z


Note

Low Risk
Additive event seeding on agent creation using existing idempotent registration builders; no auth or core runtime logic changes.

Overview
Seeds processor registration events in the initial new-agent appendBatch, right after subscription configuration and before custom events and codemode tool-provider registrations.

Adds defaultAgentProcessorRegisteredEvents in agent-stream-subscriptions.ts, which emits registration events for the standard shared processors (agent-chat, agent, and the provider’s LLM processor via buildProcessorRegisteredEvent). The New Agent flow spreads those into the preview/create event list so registration markers appear immediately in the raw stream instead of only after the stream processor runner cold-start/replay path.

Reviewed by Cursor Bugbot for commit 366d125. Bugbot is set up for automated code reviews on this repo. Configure here.

@jonastemplestein jonastemplestein marked this pull request as ready for review June 5, 2026 14:51
jonastemplestein added a commit that referenced this pull request Jun 5, 2026
## What was broken

Slack agents stopped responding. A user `@mention` becomes an
`agent/input-added` event on the routed agent stream, but **nothing
consumes it** — the LLM processors (`agent-chat` / `agent` / the
provider processor) were never registered on Slack-routed streams.
Observed live on `templestein2` stream
`/agents/slack/c09trdv61v4/ts-1780670924-517029`: `slack-agent` ran
(produced the input), but no `agent`/LLM processor existed, so no reply.

## Root cause — regression from #1370 (streams runtime cutover)

- **Old runtime:** `routedStreamBootstrapEvents` subscribed a *callable*
to `AGENT` DO `afterAppend`. Invoking it woke `AgentDurableObject` →
`onInstanceWake` registered `agent-chat`/`agent`/LLM/`agent-host` +
seeded setup events.
- **After #1370:** that was replaced with a built-in `agent-host`
processor whose `afterAppend` only runs `ensureChildAgentRunner` (+
codemode handlers). It never wakes the agent for its own stream, so the
LLM processors are never registered.
- What actually *starts* a processor is the `subscription-configured`
event (`Stream#reconcileOutboundConnections` dials a runner per
subscription key). Those were never appended for the LLM processors on
routed streams.
- Compounding: `ensureChildAgentRunner` compared against the legacy
`events.iterate.com/core/child-stream-created`, but the new runtime
emits `events.iterate.com/stream/child-stream-created`.

Dashboard-created agents were unaffected because `new.tsx` explicitly
subscribes the full processor set. **PR #1371 would not have fixed
this** — it only adds `stream-processor-registered` *marker* events
(which don't start processors) and only to the UI flow.

## The fix

- **Wake the agent for routed streams**
(`ensureAgentRunnerForOwnStream`): when `agent-host` runs on a routed
agent stream, on the `stream/created` event it initializes that stream's
`AgentDurableObject` → `onInstanceWake` registers the LLM processors and
setup events; the resulting `subscription-configured` events are what
`reconcileOutboundConnections` dials. Verified the runner replays from
offset 0 (`replayAfterOffset: snapshot?.offset ?? 0`), so `agent-host`
reliably sees `stream/created` (always offset 1).
- **Dedupe the agent-host runner:** align the bootstrap `agent-host`
subscription key with the canonical `AgentDurableObject` key (runner DOs
are keyed by `${namespace}:${path}:${subscriptionKey}`), so the two
declarations resolve to one runner.
- **Use the new-runtime `events.iterate.com/stream/` prefix** at the OS
call-sites that compare against new-runtime core events: the broken
`child-stream-created` check (local constants), the project agents-root
jsonata matcher, and the stream-composer UI examples.

## Verification

- Full-repo `pnpm typecheck` (18 projects), `oxlint`, `oxfmt`
- Affected OS unit tests pass
- Not yet deployed / round-tripped on a preview — recommend a preview
deploy + one test `@mention` before prod (`Preview / e2e` is otherwise
skipped on PRs).

## Scope note

An earlier revision also did a broad `events.iterate.com/core/` →
`/stream/` rename across the shared package and the separate
**events.iterate.com** app. That **broke the events runtime e2e**
(append → 500) and is unrelated to this bug, so it was reverted out of
this PR. If we still want the events platform on the `/stream/` prefix
it needs its own investigation — tracked as a follow-up.

## Follow-ups (found while auditing #1370)

- `ProjectDurableObject.afterAppend` is **orphaned**: the old runtime
forwarded lifecycle events to the project config-worker `afterAppend`
hook; the new built-in `project-lifecycle` processor has no
`afterAppend` and nothing calls it.
- `CodemodeSession.afterAppend` is orphaned (likely benign — resolves
locally via `appendAndConsume`).
- `agents.e2e.test.ts` has vacuous `/core/error-occurred` assertions;
worth real Slack-path e2e coverage so this can't regress silently.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- CLOUDFLARE_PREVIEW -->
## Environment Config Lease
<!-- CLOUDFLARE_PREVIEW_STATE -->
<!--
{
  "apps": {
    "os": {
      "appDisplayName": "OS",
      "appSlug": "os",
      "status": "deployed",
      "updatedAt": "2026-06-05T19:21:55.576Z",
      "headSha": "2ba51d83ff4b86b9ca37a30b463cd3cd9e1f4d54",
      "message": null,
      "publicUrl": "https://os.iterate-preview-2.com",
"runUrl": "https://github.com/iterate/iterate/actions/runs/27035212234",
      "shortSha": "2ba51d8"
    }
  },
  "environmentConfigLease": {
    "dopplerConfig": "preview_2",
    "leasedUntil": 1780690796123,
    "leaseId": "23930c5a-2e1b-49b4-b10a-c83b489c0794",
    "slug": "preview-2",
    "type": "environment-config-lease"
  }
}
-->
<!-- /CLOUDFLARE_PREVIEW_STATE -->
Lease: `preview-2`
Doppler config: `preview_2`
Type: `environment-config-lease`
Leased until: 2026-06-05T20:19:56.123Z

### OS
Status: deployed
Commit: `2ba51d8`
Preview: https://os.iterate-preview-2.com
[Workflow
run](https://github.com/iterate/iterate/actions/runs/27035212234)
Updated: 2026-06-05T19:21:55.576Z
<!-- /CLOUDFLARE_PREVIEW -->

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Touches agent stream bootstrap and durable-object initialization on
every routed agent stream; wrong event matching or wake ordering could
affect non-Slack agents, but changes are narrowly scoped to host
processor and Slack routing.
> 
> **Overview**
> Restores **Slack-routed agent streams** after the streams runtime
cutover (#1370): routed streams only got `slack-agent` + `agent-host`,
so `agent/input-added` events were never consumed because LLM processors
were never registered.
> 
> **`ensureAgentRunnerForOwnStream`** initializes the stream’s
`AgentDurableObject` on `events.iterate.com/stream/created` (via
`agent-host` `afterAppend`, using **`keepAlive`** to avoid deadlocking
catch-up). That runs `onInstanceWake`, which appends the LLM processor
subscriptions and setup events.
> 
> **Slack bootstrap** now uses
**`agentProcessorSubscriptionConfiguredEvent`** so the routed
`agent-host` subscription key matches `AgentDurableObject`, deduping to
a single runner.
> 
> **Event type alignment** for the new runtime: `child-stream-created`
and related core lifecycle types use `events.iterate.com/stream/…`
instead of legacy `…/core/…` in agent host logic, the agents-root
jsonata matcher, and stream composer presets.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
2ba51d8. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant