Skip to content

Sequencing

Don’t define all types before building the first end-to-end flow. The Discord hourly test is the forcing function. Wire that one path and let the types prove themselves.

Starting point

@arbe/core currently has three record types: agent, house, room. The agent runtime (HusAgent DO) has hardcoded mention and ambient trigger pipelines. Activation is implicit in the DO’s handleStreamEvent method. There’s no concept of “I hold capability X against resource Y” — the agent just has credentials and knows how to post to streams.

arbe’s local execution model (run, session, sandbox, task) is fully built but lives entirely in repo-local SQLite and task files. Nothing projects into shared records yet.

The bridge between these two systems is the actual work.

Three missing interfaces

The record types are the easy part. The hard part is the runtime wiring — the actual functions that need to exist at the boundary.

The first is capability resolution at activation time. See capabilities.

The second is shared run creation. When an activation crosses a shared boundary (remote dispatch, external resource, multi-agent), the dispatcher creates a run record in the substrate at birth. arbe’s local observability can mirror this for the operator’s local view, but the substrate record is primary. Local-only runs (repo coding work) never touch the substrate.

The third is activation dispatch. A generic dispatch(activationPolicy, event) → run path that any adapter can use. See activation.

Concrete order

  1. Resource records and secret bindings first. They unblock everything downstream — you can’t express activation policies without a resource to point at, and the agent can’t act without credentials. Add the schemas to @arbe/core, the mutation builders, a migration. Create a Discord channel resource record and a secret binding by hand.

  2. Tool records second. Define send-message as a tool record. This is mostly bookkeeping but it makes capability resolution expressible.

  3. Capability resolution third. Wire resolveCapabilities so the DO can ask “what tools can I use against what resources?” Refactor the agent’s stream-posting code to go through a permission check on tool + resource records instead of just having baked-in credentials.

  4. Activation policies fourth. Replace trigger_mode on agent content. Wire the mention and ambient pipelines to read from policy records. This is the biggest refactor in the worker — the current handleStreamEvent pipeline needs to become policy-driven.

  5. Run records and session rooms fifth. Start with shared runs only (dispatched or resource-involving work). Create session rooms using the existing room creation flow. Local runs stay in SQLite.

  6. Artifact records sixth. Make the agent create an artifact record when it posts a Discord message (with the remote message ID). This closes the “terminal text is not enough” loop.

  7. Memory records last. The current DO SQLite working memory is fine for now — durable semantic memory can wait until the execution path is solid.

What changes conceptually

Stop treating “automation” as a thing in itself. Treat it as agent plus activation policy plus capabilities plus optional sandbox plus result policy.

Stop treating runtime-local SQLite as general memory. It is working memory.

Stop treating local task state as the universal planning model. It is a code-work planning model.

Stop treating terminal output as the result. Results need durable identity.

Start modeling external targets as resources, not just vague integrations.

Start treating secrets as a named seam. A capability without secret management is theatre.

The one-sentence version

Wire credentialed tool execution to the permission system, add cron activation to Durable Objects, and figure out agent memory — then the substrate becomes an automation engine without any new primitives.