AI AGENTS

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.

MCP INTEGRATION

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
Set up MCP in your editor →
claude_desktop_config.json
{
  "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"

PATTERNS

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
})
COMPOSITION

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 →
Agents App
@nolag/agents
shared actors
Chat App
@nolag/chat
EXAMPLE

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);
});
COMPARISON

NoLag vs building it yourself

CapabilityDIYNoLag
Worker pooling & routingBuild on Redis/KafkaTag-based dispatch built in
Persistent message queuesConfigure message brokerQoS 2 + retained messages
Shared stateRedis/custom storeBlackboard pattern
Audit trailCustom loggingObserve pattern + event stream
Presence & heartbeatsCustom health checksBuilt-in presence API
Access controlCustom auth layerPer-topic ACL

Ready to coordinate your agents?

Start free. No credit card required. Ship your first agent workflow in minutes.