---
title: "Agent-to-Agent Communication"
description: "Use host tools to let agents communicate with each other."
skill: true
---

Agents communicate through [host tools](/docs/agent-os/tools). You define a toolkit that lets one agent send work to another, and the agent calls it like any other CLI command.

## Example: code writer + reviewer

This example creates a writer agent with a `review` tool. When the writer calls the tool, it reads the file from the writer's VM, writes it to a separate reviewer VM, and sends a review prompt.

<CodeGroup stacked>
```ts @nocheck server.ts
import { agentOs } from "rivetkit/agent-os";
import { setup } from "rivetkit";
import common from "@rivet-dev/agent-os-common";
import pi from "@rivet-dev/agent-os-pi";
import { toolKit, hostTool } from "@rivet-dev/agent-os-core";
import { createClient } from "rivetkit/client";
import { z } from "zod";

// Tool that bridges the writer to the reviewer
const reviewToolkit = toolKit({
  name: "review",
  description: "Send code to the reviewer agent",
  tools: {
    submit: hostTool({
      description: "Submit a file for code review",
      inputSchema: z.object({
        path: z.string().describe("Path to the file to review"),
      }),
      execute: async (input) => {
        const client = createClient<typeof registry>("http://localhost:6420");
        const writerHandle = client.writer.getOrCreate(["my-project"]);
        const reviewerHandle = client.reviewer.getOrCreate(["my-project"]);

        // Read file from writer, write to reviewer
        const content = await writerHandle.readFile(input.path);
        await reviewerHandle.writeFile(input.path, content);

        // Ask the reviewer to review
        const session = await reviewerHandle.createSession("pi", {
          env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! },
        });
        const response = await reviewerHandle.sendPrompt(
          session.sessionId,
          `Review the code at ${input.path} and list any issues.`,
        );
        await reviewerHandle.closeSession(session.sessionId);

        return { review: response };
      },
    }),
  },
});

// Writer has the review toolkit, reviewer is plain
const writer = agentOs({
  options: { software: [common, pi], toolKits: [reviewToolkit] },
});
const reviewer = agentOs({
  options: { software: [common, pi] },
});

export const registry = setup({ use: { writer, reviewer } });
registry.start();
```

```ts @nocheck client.ts
import { createClient } from "rivetkit/client";
import type { registry } from "./server";

const client = createClient<typeof registry>("http://localhost:6420");
const writerAgent = client.writer.getOrCreate(["my-project"]);

const session = await writerAgent.createSession("pi", {
  env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! },
});

// The writer will call `agentos-review submit --path /home/user/api.ts`
// when it's ready for a review
await writerAgent.sendPrompt(
  session.sessionId,
  "Write a REST API at /home/user/api.ts, then submit it for review.",
);
```
</CodeGroup>

The writer agent sees the review tool as a CLI command:

```bash
agentos-review submit --path /home/user/api.ts
```

When the writer calls this, the host tool reads the file from the writer's VM, writes it to the reviewer's VM, and sends a prompt to the reviewer. The review result is returned to the writer as JSON.

## Why host tools?

Host tools are the natural communication layer between agents because:

- **The agent doesn't need to know about other agents.** It just calls a tool. You can swap the implementation without changing the agent's behavior.
- **No credentials in the VM.** The host tool executes on the server, so it can access other agents directly without exposing connection details.
- **Composable.** Chain any number of agents by adding more tools. Each tool is a self-contained bridge to another agent.

## Recommendations

- Each agent has its own isolated VM and filesystem. Use `readFile`/`writeFile` in host tools to pass files between them.
- Use [Queues](/docs/agent-os/queues) when agents need to process work asynchronously.
- Use [Workflows](/docs/agent-os/workflows) to make multi-agent pipelines durable across restarts.
