Skip to main content
Core

Design Patterns

Patterns for agent keys, subagents, agent-to-agent messages, workflows, schedules, and shared credentials.

Each agent is an Actor, so agent apps use the same building blocks as the rest of Rivet: keys pick the agent, and agents call other Actors.

One Agent per Key

The key decides which conversation a prompt continues. Pick it from what the agent should remember:

  • Per user: a personal assistant remembers everything a user has asked, across every chat.
  • Per thread: each Slack thread, support ticket, or chat tab is its own conversation.
  • Per task: each job, such as fixing one GitHub issue, starts fresh in its own sandbox. When it’s done, an action that calls c.destroy() deletes the agent and its sandbox, like finish below.
assistant/:userIdAssistantremembers the usergetOrCreateslackThread/:channel/:tsSlack threadone conversationgetOrCreateissueFixer/:repo/:issueIssue fixerone fix, then deletedgetOrCreate

Keys are arrays, so a channel id or repository name from a webhook can’t break the key’s structure. See Actor Keys.

Lead Agent with Subagents

A lead agent hands a focused task to a specialist with its own tools and waits for its answer. The specialist starts with a fresh context, so only the answer comes back.

Support agentask_specialist toolOrders specialistget_order toolEngineering specialistsandboxquestion

See Subagents.

Agents Messaging Each Other

When an agent hands work off and doesn’t need the answer, it sends a message instead of waiting. The receiving agent schedules its own prompt, so the message survives the sender going away.

Coder agentReviewer agentkey: repositoryrequestReview()returns right away

See Agent-to-Agent Messages.

Agent as a Workflow Step

When the work has fixed steps, waits, or retries, let a workflow drive the agent. Each step calls abort first, so a retried step doesn’t collide with a run the previous attempt left going.

Workflow steptriageAgentabort, prompt

See Workflows.

Scheduled Agents

An agent can wake itself on a schedule and sleep between runs.

Cron0 9 * * *Agentasleep between runsprompt

See Schedules.

Credentials Shared per Tenant

Start agent keys with the tenant id, and pick the credentials Actor from it. Every agent in a tenant shares one set of model logins, and never sees another tenant’s.

[“acme”, “alice”][“acme”, “bob”][“globex”, “carol”]credentials acmecredentials globex

See User Subscriptions.

Anti-Patterns

One Agent for Every User

An agent runs one prompt at a time. With a single key for everyone, a prompt from one user throws while another user’s prompt is running, and every user shares one session.

import { createClient } from "rivetkit/client";
import type { registry } from "./agent-per-key/server";

const client = createClient<typeof registry>();

export async function answer(userId: string, message: string) {
	const assistant = client.assistant.getOrCreate(["support"]);
	await assistant.prompt(`${userId}: ${message}`);
	return assistant.getLastAssistantText();
}

Solution: Key the agent by user, thread, or task.

A New Key per Request

A new key creates a new agent with an empty session, so the agent forgets the conversation after every message and leaves an Actor behind.

import { createClient } from "rivetkit/client";
import type { registry } from "./agent-per-key/server";

const client = createClient<typeof registry>();

export async function answer(message: string) {
	const assistant = client.assistant.getOrCreate([crypto.randomUUID()]);
	await assistant.prompt(message);
	return assistant.getLastAssistantText();
}

Solution: Reuse the key of the conversation the message belongs to.

Where to Go Next

GoalRead
Give agents model accessLLM API Keys
Give the agent your own APIsCustom Tools
Let the agent run commands and edit filesSandboxes, then Built-in Tools
Run agents on your users’ own subscriptionsUser Subscriptions
Wait for a person before a risky actionHuman in the Loop
Share a result through a linkScoped Access with JWTs
Talk to users in Slack, Linear, GitHub, or DiscordSlack and the other connectors
See what happens while an agent answers a promptSession Lifecycle
Build a chat UIReact SDK
Secure and deploy agentsSecurity Model, then Deploy