Skip to content

Agents

maypop.agent runs a full assistant loop in the page: it talks, calls the tools you give it, reads the results, and keeps going until it has an answer. You decide what it can do by choosing its tools.

interface MaypopAgent {
create(config: MaypopAgentConfig): Promise<MaypopAgentSession>;
driveTools(opts?: { prefix?: string }): MaypopAgentToolDef[];
conversations: MaypopAgentConversations;
}
interface MaypopAgentConfig {
systemPrompt: string;
model?: "fast" | "smart";
tools?: MaypopAgentToolDef[];
chips?: (string | MaypopAgentChip)[];
thinkingLevel?: "off" | "low" | "medium" | "high";
conversationId?: string;
}
interface MaypopAgentToolDef {
name: string;
label?: string;
description: string;
parameters: Record<string, unknown>;
execute: (
params: Record<string, unknown>,
) => Promise<string | MaypopAgentToolResult> | string | MaypopAgentToolResult;
}
interface MaypopAgentToolResult {
text: string;
details?: unknown;
terminate?: boolean;
}
interface MaypopAgentChip {
label: string;
prompt: string;
}
interface MaypopAgentSession {
send(text: string): void;
abort(): void;
getMessages(): MaypopAgentMessage[];
readonly streaming: boolean;
readonly conversationId: string | null;
ready(): Promise<void>;
readonly chips: MaypopAgentChip[];
subscribe(onChange: () => void): () => void;
}
interface MaypopAgentMessage {
role: "user" | "assistant" | "tool";
text: string;
toolCalls?: {
name: string;
arguments: unknown;
label: string;
done: boolean;
}[];
streaming?: boolean;
}
await maypop.ready();
const session = await maypop.agent.create({
systemPrompt:
"You help a household plan meals from their shared recipe list.",
conversationId: "kitchen",
chips: ["What can I cook tonight?", "Plan the week"],
tools: [
{
name: "list_recipes",
label: "Reading recipes",
description: "List every saved recipe.",
parameters: { type: "object", properties: {} },
execute: async () =>
JSON.stringify(await maypop.kv.list({ prefix: "recipe/" })),
},
],
});
await session.ready();
session.subscribe(() => render(session.getMessages()));
session.send("What can I cook tonight?");
  • subscribe tells you something changed; read the transcript with getMessages().
  • parameters is a JSON Schema for the tool’s arguments. If execute throws, the error goes back to the model so it can recover.
  • maypop.agent.driveTools() gives the agent ready-made tools to list, read, create and delete Drive files, optionally under a prefix.
  • maypop.mcp.tools() returns tools in the same shape, so an agent can use the app’s connected services.
  • The default tier is smart; thinkingLevel trades speed for more careful answers.

With a conversationId, the conversation is saved for the person using the app and picks up where they left off. maypop.agent.conversations lists, reads and deletes them:

interface MaypopAgentConversations {
list(): Promise<MaypopAgentConversationSummary[]>;
get(id: string): Promise<MaypopAgentConversation | null>;
delete(id: string): Promise<void>;
}

Conversations are stored in the app’s KV store under ~chat/, so they follow its saved-data policy.

Agents need the same access as maypop.ai: people with view-only access and anonymous visitors can’t start one, and every turn uses the person’s AI credits.