Orchestration
Agent-to-Agent Communication
Agents communicate through host 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
Section titled “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.
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 reviewerconst 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 plainconst writer = agentOs({ options: { software: [common, pi], toolKits: [reviewToolkit] },});const reviewer = agentOs({ options: { software: [common, pi] },});
export const registry = setup({ use: { writer, reviewer } });registry.start();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 reviewawait writerAgent.sendPrompt( session.sessionId, "Write a REST API at /home/user/api.ts, then submit it for review.",);The writer agent sees the review tool as a CLI command:
agentos-review submit --path /home/user/api.tsWhen 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?
Section titled “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.