The coordination layer for multi-agent systems
Dispatch work, share state, observe decisions, and gate actions - on the same infrastructure that powers chat, notifications, and live dashboards. Build with our MCP server from your IDE.
Multi-agent systems need coordination infrastructure
Most teams build it from scratch on top of Redis, Kafka, or raw WebSockets. NoLag provides the patterns - task dispatch, shared state, approval gates, observability - so you can focus on agent logic instead of plumbing.
Build with AI, for AI
NoLag ships a full Model Context Protocol (MCP) server. Connect Claude Desktop, Cursor, or any MCP-compatible AI assistant and let it manage your entire agent infrastructure - create apps, rooms, actors, dispatch tasks, and query state using natural language.
- 47+ tools for apps, rooms, actors, scopes, messaging, and agent observability
- Let your AI assistant scaffold entire agent workflows from a prompt
- Dispatch tasks, read blackboard state, and monitor agents - all from your IDE
{
"mcpServers": {
"nolag": {
"url": "https://api.nolag.app/mcp/sse",
"headers": {
"Authorization": "Bearer YOUR_API_KEY"
}
}
}
}Then ask: "Create an agents app with a research workflow room and 3 worker actors"
Six coordination primitives
Handoff
Dispatch tasks to workers by capability tags. Built-in pooling, routing, and result collection.
await room.handoff.dispatch({
type: "summarize",
payload: { url },
capabilities: ["research"],
});Inbox
Direct actor-to-actor messaging. Route messages to specific agents by ID without broadcasting.
await room.inbox.send("agent-42", {
type: "review",
content: draft,
});Blackboard
Shared key-value state with versioning. All agents see the same state, with conflict-free updates.
await room.blackboard.set("plan", {
steps: ["research", "draft", "review"],
currentStep: 0,
});Observe
Real-time event stream for monitoring. Watch every decision, state change, and task completion.
room.observe.on("*", (event) => {
log(event.type, event.agent, event.data);
});Approve
Human-in-the-loop gating. Pause agent workflows until a human approves, rejects, or modifies.
const approval = await room.approve.request({
action: "send-email",
draft: emailContent,
});Tools
Remote tool invocation and response. Let agents call tools hosted by other agents or services.
const result = await room.tools.invoke(
"web-search",
{ query: "latest AI news" },
);Multi-Tenant Isolation
Automatic per-tenant communication isolation. Assign actors to access scopes and all MQTT topics are partitioned - zero code changes, zero room duplication.
// Create a scope for each tenant
const scope = await api.createScope({
slug: 'client-acme',
name: 'Acme Corporation'
})
// Assign actors - isolation is automatic
await api.updateActor(actorId, {
accessScopeId: scope.accessScopeId
})Compose with other Blueprints
Agents Blueprint composes naturally with Chat, Notify, Track, and other Blueprints via cross-app actor access. Build an agentic chatbot by connecting an agents app with a chat app - shared actors bridge the two.
Read the composition guide →End-to-end orchestration
Dispatch research to a capable worker, collect results, request human approval, then hand off to a publisher agent. All state changes are observable in real time.
- Tag-based capability routing
- Shared blackboard for workflow state
- Human-in-the-loop approval gates
- Full observability on every event
import { NoLagAgents } from "@nolag/agents";
const agents = new NoLagAgents(ORCHESTRATOR_TOKEN);
await agents.connect();
const room = agents.joinRoom("research-workflow");
// 1. Set shared state
await room.blackboard.set("goal", {
topic: "Quarterly revenue analysis",
sources: ["SEC filings", "earnings calls"],
});
// 2. Dispatch research task to any capable worker
const task = await room.handoff.dispatch({
type: "research",
payload: room.blackboard.get("goal"),
capabilities: ["research", "finance"],
});
// 3. Wait for result, then dispatch review
room.handoff.onResult(async (result) => {
if (result.taskId === task.id) {
// Request human approval before publishing
const approval = await room.approve.request({
action: "publish-report",
content: result.data,
});
if (approval.approved) {
await room.inbox.send("publisher-agent", {
type: "publish",
report: result.data,
});
}
}
});
// 4. Observe everything
room.observe.on("*", (event) => {
console.log(`[${event.agent}] ${event.type}:`, event.data);
});NoLag vs building it yourself
| Capability | DIY | NoLag |
|---|---|---|
| Worker pooling & routing | Build on Redis/Kafka | Tag-based dispatch built in |
| Persistent message queues | Configure message broker | QoS 2 + retained messages |
| Shared state | Redis/custom store | Blackboard pattern |
| Audit trail | Custom logging | Observe pattern + event stream |
| Presence & heartbeats | Custom health checks | Built-in presence API |
| Access control | Custom auth layer | Per-topic ACL |
Ready to coordinate your agents?
Start free. No credit card required. Ship your first agent workflow in minutes.