---
title: Blueprint Composition for Agents
description: How to compose the agents Blueprint with chat, notify, track, and other Blueprints on one shared client.
---

# Blueprint Composition

Combine the agents Blueprint with other Blueprints to build powerful real-time applications.

## How Composition Works

NoLag Blueprints are independent apps within the same project. Each Blueprint manages its own rooms and topics. Composition happens through **cross-app actor access**: one actor, with one token and one connection, can use several apps at the same time.

For example, an actor representing a chatbot can attach a `@nolag/chat` wrapper (for user-facing messaging) and a `@nolag/agents` wrapper (for AI coordination) to the same client. The actor bridges the two apps, forwarding user messages to the agent workflow and sending agent responses back to the chat.

### Key concepts

- **Actors are created at the project level.** An app in its default `open` access mode admits every active actor in the project; a `restricted` app admits only actors granted access to it.
- **One token, one client.** The actor connects once with `NoLag(token)`; every wrapper takes that `client` in its options and names its own app with `appName`.
- Each wrapper keeps its own rooms and topics on the shared connection.
- The bridge code listens on one wrapper and publishes on the other.

## Example: Agentic Chatbot

A customer support chatbot that uses `@nolag/chat` for the user-facing interface and `@nolag/agents` for the AI backend. When a user sends a message, the bot dispatches it as a task to a customer-support agent, waits for the result, and posts the response back to the chat room.

```typescript [TypeScript]
import { NoLag } from "@nolag/js-sdk";
import { NoLagChat } from "@nolag/chat";
import { NoLagAgents, Handoff } from "@nolag/agents";

// One actor, one connection, two apps
const client = NoLag(BOT_TOKEN);
const chat = new NoLagChat({ client, appName: CHAT_APP_SLUG, username: "support-bot" });
const agents = new NoLagAgents({
  client,
  appName: AGENTS_APP_SLUG,
  agentId: "support-bridge",
  presence: { name: "support-bridge", role: "orchestrator" },
});

await client.connect();
await Promise.all([chat.ready(), agents.ready()]);

// User-facing chat room (seeded by the chat blueprint)
const chatRoom = chat.joinRoom("general");

// Agent coordination room (seeded by the agents blueprint)
const agentRoom = agents.room("default-workflow");
const handoff = new Handoff(agentRoom);

// Publishers never receive their own messages, so this fires only for other users
chatRoom.on("message", async (msg) => {
  const result = await handoff.dispatch(
    "customer-support",
    {
      userId: msg.userId,
      text: msg.text,
      history: chatRoom.getMessages().map((m) => ({ from: m.username, text: m.text })),
    },
    { waitForResult: true, timeout: 30000 },
  );

  if (result && result.status === "success") {
    chatRoom.sendMessage(String(result.payload.response));
  }
});
```

### Architecture

| Component | Blueprint | Role |
| --- | --- | --- |
| Chat UI | `@nolag/chat` | User-facing chat rooms with presence and typing |
| Bot bridge | Both | Listens to chat, dispatches to agents, sends responses |
| AI workers | `@nolag/agents` | Process user queries with an LLM, return responses |

## Example: Monitored Delivery Fleet

A delivery fleet that uses `@nolag/track` for real-time GPS tracking and `@nolag/agents` for intelligent monitoring. `@nolag/track` evaluates geofences on the client for every location update it receives, so when a vehicle enters one, the monitor dispatches an analysis task and records the outcome on the Blackboard.

```typescript [TypeScript]
import { NoLag } from "@nolag/js-sdk";
import { NoLagTrack } from "@nolag/track";
import { NoLagAgents, Handoff, Blackboard } from "@nolag/agents";

const client = NoLag(MONITOR_TOKEN);
const track = new NoLagTrack({ client, appName: TRACK_APP_SLUG, assetId: "fleet-monitor" });
const agents = new NoLagAgents({
  client,
  appName: AGENTS_APP_SLUG,
  agentId: "fleet-monitor",
  presence: { name: "fleet-monitor", role: "orchestrator" },
});

await client.connect();
await Promise.all([track.ready(), agents.ready()]);

// Tracking zone (seeded by the track blueprint) with a client-side geofence
const fleet = track.joinZone("fleet-zone");
fleet.addGeofence({
  id: "depot",
  shape: "circle",
  center: { lat: -37.8136, lng: 144.9631 },
  radiusMeters: 250,
});

const agentRoom = agents.room("default-workflow");
const handoff = new Handoff(agentRoom);
const blackboard = new Blackboard(agentRoom, agents.agentId);

// When a vehicle enters the geofence, trigger agent analysis
fleet.on("geofenceTriggered", async (event) => {
  if (event.type !== "enter") return;

  const result = await handoff.dispatch(
    "logistics",
    { assetId: event.assetId, geofenceId: event.geofenceId, point: event.point },
    { waitForResult: true, timeout: 30000 },
  );

  // Record the outcome on shared state (read-modify-write, last writer wins)
  if (result && result.status === "success") {
    const status = (blackboard.get("fleet-status") as Record<string, unknown> | undefined) ?? {};
    blackboard.set("fleet-status", { ...status, [event.assetId]: result.payload.status });
  }
});
```

## Composition Patterns

### Event bridge

The simplest pattern: listen for events on one Blueprint and trigger actions on another. The chatbot example above uses this: chat messages trigger agent tasks.

### Shared state sync

Use the Blackboard pattern to maintain state that is derived from events in other Blueprints. The fleet example writes fleet status from tracking events.

### Approval pipeline

Combine `@nolag/agents` (Approve pattern) with `@nolag/notify`. A bridge handles `approve.onRequest()` by sending the request as a notification; when a human answers it, the bridge calls `respond("approved")` or `respond("rejected", reason)` and the agent workflow continues.

## Which Blueprints compose well?

| Combination | Use case |
| --- | --- |
| Agents + Chat | Agentic chatbots, AI-assisted customer support |
| Agents + Notify | Agent-triggered notifications, approval requests |
| Agents + Track | Intelligent fleet monitoring, autonomous logistics |
| Agents + Dash | AI-powered dashboards, automated reporting |
| Agents + IoT | Autonomous device management, predictive maintenance |
