attend
OfficialServes as an LLM judge backend: with --judge decisions (reading OPENAI_API_KEY) and --judge-model, the server sends each settled event window to OpenAI to choose a route (interrupt, queue, note, ask, skip, wait) for the agent.
Used as a durable persistence store for the event log and decisions via --store postgres:<url>, keeping windows, judgments and delivery state across restarts (requires the pg package).
Used as a persistence store for the event log and decisions via --store [redis](/mcp/servers/integrations/redis):<url>, allowing a shared attention service across agents and processes (requires the redis package).
Used as a built-in local persistence store via --store [sqlite](/mcp/servers/integrations/sqlite):<file>, persisting every step and decision to disk.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@attendwait for the next decision on ops/db and wake me only if it's an interrupt"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Picture an agent that watches your app. The app never stops talking: log lines, messages, clicks, alerts. Wake the agent on every event and it never finishes a thought. Put it behind a debounce and it sleeps through the one message that mattered.
attend holds each scope's events until they add up to something, asks a judge what the agent should do, and hands your app one decision. Your app keeps the final say in how that decision runs. In the sample below, a failed build waits, and the user's question wakes the agent with both.
import { createAttend, defaultNotice } from '@acquiredintelligence/attend';
const attend = createAttend({
kind: { 'user.message': 'flush', 'build.failed': 'closing' },
judge: async ({ window }) => ({ route: window.reason === 'flush' ? 'interrupt' : 'note' }),
sink: (decision) => console.log(`[${decision.route}]\n${defaultNotice(decision)}`),
});
void attend.run();
await attend.push('session-1', { name: 'build.failed', text: 'Build 4521 failed: 1 test' });
await attend.push('session-1', { name: 'user.message', text: 'can you look?' });The build failure alone never wakes the agent. The user's message settles the window at once, and the agent hears both lines in one notice:
[interrupt]
Build 4521 failed: 1 test
can you look?
Attend to this now, even mid-task.Install
npm install @acquiredintelligence/attendattend needs Node 22.13 or later and ships ESM only. The engine has no runtime dependencies. Before production, replace the function judge with a real judge and pass store a database store; without one, state lives in memory.
A Python port for asyncio, with the same semantics and the same decision ids, lives in python/.
Related MCP server: voice-gate
See it decide
In a clone of this repo, pnpm demo streams a short CI story from a real MCP Events server into attend and prints what the agent hears. It needs no API key and no database. The source is examples/demo.ts.
attend demo: a CI server streams MCP Events, and attend decides what the agent hears.
0.0s event ci.started {"run":4521,"branch":"main"}
0.1s event ci.log {"line":"pnpm install"}
0.2s event ci.log {"line":"pnpm test"}
0.3s event ci.log {"line":"211 passed, 1 failed"}
0.4s event ci.test_failed {"test":"checkout applies the coupon"}
0.6s settle 5 events (closing)
0.6s judge wait (hold the window and judge it again)
1.0s event comment.created {"author":"sam","body":"can you look?"}
1.0s settle 6 events (flush), merged with the held window
1.0s judge interrupt
1.0s deliver interrupt
ci.started {"run":4521,"branch":"main"}
ci.log {"line":"pnpm install"}
ci.log {"line":"pnpm test"}
ci.log {"line":"211 passed, 1 failed"}
ci.test_failed {"test":"checkout applies the coupon"}
comment.created {"author":"sam","body":"can you look?"}
Attend to this now, even mid-task.
1.8s event deploy.finished {"env":"staging","sha":"9f3c2e1"}
2.0s settle 1 event (closing)
2.0s judge note
2.0s deliver note
deploy.finished {"env":"staging","sha":"9f3c2e1"}
Background only. No reply is needed.
7 events in, 2 deliveries out. Waking on every event would have run the agent 7 times.attend held the log lines until the failed test closed the window. The judge chose wait, so the user's comment joined the held window, and one interrupt carried all six events to the agent. The deploy arrived as a note.
What you get
6 routes. The judge picks
interrupt,queue,note,ask,waitorskip, and your app carries it out.Windows that settle when an act ends. A finished build or a message to the agent settles the window. A log line never wakes the agent on its own.
Your choice of judge. TypeSafe's Jev, the OpenAI Decisions API, any model through
llmJudge, or a plain function.4 stores. Memory, SQLite, Postgres and Redis, each crash-tested at every commit boundary in CI.
At-least-once delivery. A decision keeps its id across retries, so your sink can drop repeats.
0 runtime dependencies when embedded, or one command to serve decisions over MCP Events.
How it works
The judge picks the route, and your app carries it out. interrupt means the agent should hear this now, and your handler decides whether that cancels the turn, steers it or shows a banner. Raw events never leave attend. Only settled, judged decisions do. How attend works walks through each step, and the reference lists every kind, route and default.
Run it in your process or beside it
Embedded |
| |
What |
| The same engine as a process of its own: a sidecar next to your app |
Events in |
|
|
Decisions out | Your | MCP Events: |
Use it for | Real-time agents. The default. Flush to delivery stays in-process, with no network hop. | Apps that are not TypeScript, several agents on one firehose, or a team that wants one shared attention service |
To run the sidecar, see Run attend as a sidecar with attend serve.
Read the docs
Page | Read it to |
understand scopes, windows, settling and the decision log | |
look up kinds, routes, guarantees and defaults | |
pick and configure Jev, the Decisions API, | |
write an idempotent sink and a dead-letter handler | |
run on memory, SQLite, Postgres or Redis, and share a store between processes | |
wire attend in front of a Mastra agent with one sink | |
subscribe a scope to an MCP Events stream with | |
send events over HTTP and subscribe agents over MCP | |
look up every flag and the ingest wire format | |
make settling deterministic in your tests | |
implement |
Let your coding agent wire it in
The repo ships an Agent Skill that leads your coding agent through wiring attend into your app. It works out which events the app emits, which of them are signals, and which deserve which reaction. It tells you in a few lines what it will do, asks one batch of questions with a recommended default for each, and wires it in with one small module and a few call sites at your existing event chokepoints. To install it in Claude Code:
/plugin marketplace add acquiredintelligence/attend
/plugin install attend@attendFor Codex or Cursor, copy skills/attend into your project's .agents/skills/. The npm package includes the skill at node_modules/@acquiredintelligence/attend/skills/attend. The third-party Vercel Labs CLI also installs it with npx skills add acquiredintelligence/attend. That CLI is not part of this project.
Status
attend is v0, and its API can change before 1.0. MCP Events is a working-group draft, so its wire shapes can change too. @acquiredintelligence/attend/mcp follows the current draft.
License
MIT. Built by the team behind Zettel.
This server cannot be deployed
Maintenance
Related MCP Connectors
Hosted MCP memory and agent control plane for durable conversations, jobs, and operations.
Join durable public agent discussions and invite-only private group rooms through MCP.
- AgenTruxOAuthcom.agentrux
Authenticated event topics for agent-to-agent messaging with per-agent credentials and audit logs.
Build and manage AI-native customer support agents from Claude or any MCP client.
Related MCP Servers
- AlicenseNot gradedqualityBmaintenanceEnables AI agents and applications to send audio notifications with text-to-speech, message streaming, agent-to-agent conversations, and web push notifications through a persistent message store and MCP integration.43 npm1MIT
- AlicenseAqualityBmaintenanceEnables MCP clients to submit completed speech or typed text to a self-hosted decision engine and receive judgments such as ordinary speech, command, retained thought, uncertainty, or no action, along with session and decision inspection.3MIT
- AlicenseCqualityAmaintenanceEnables real-time voice agents and streaming audio pipelines to detect conversational turn completion, distinguishing finished speech turns from mid-sentence hesitation pauses using acoustic VAD and semantic scoring. It provides low-latency decision and telemetry output through a native MCP interface for integration with MCP-compliant clients.47MIT
- FlicenseNot gradedqualityAmaintenanceEnables real-time full-duplex voice agents to classify user interruptions, backchannels, and acoustic echo, and to arbitrate turn-taking with context rollback via MCP.7-