Install
Three published packages — pick the ones that fit your shape.
# Embed the runtime in your own app npm install @agentmug/runtime # Use the CLI (humans + agent-driven) npm install -g @agentmug/cli # Expose AgentMug agents to Claude Code / Cursor (configured, not installed) # See "Use from Claude Code / Cursor" below
Hello agent
The 10-line minimum. Pass a parsed .agent file + a prompt + an Anthropic key. quickRun wires in-memory adapters so you don't need a database to get started.
import { quickRun, parseAgentFile } from "@agentmug/runtime";
import { readFileSync } from "node:fs";
const agentFile = parseAgentFile(JSON.parse(readFileSync("./hello.agent", "utf8")));
const result = await quickRun({
agentFile,
userInput: "Say hi in 5 words.",
llm: { anthropicApiKey: process.env.ANTHROPIC_API_KEY! },
onEvent: (e) => e.type === "token" && process.stdout.write(e.content),
});
console.log("\n→", result.totalTokens, "tokens");Full runnable copy in examples/hello-agent.
.agent file format
A .agent file is a declarative JSON document: name, description, system prompt, model, tool list, input/output shapes, parameters. Portable. Version-controllable. Forkable.
{
"$schema": "https://agentmug.com/schemas/agent.v1.json",
"id": "email-triage",
"name": "Email Triage",
"description": "Sorts unread Gmail and drafts replies.",
"blueprint": {
"primaryModel": "claude-sonnet-4-6",
"systemPrompt": "You triage emails...",
"tools": ["gmail.send", "memory.save", "ask_user"]
},
"parameters": [{
"name": "source_file_1",
"label": "Source table 1",
"type": "file",
"required": true,
"artifact": {
"kind": "table",
"accepts": [".csv", ".xlsx"],
"structure": ["Sheet \"Invoices\" columns: invoice_id, amount, due_date"]
}
}],
"inputs": { "accepts": ["text"] },
"outputs": { "shape": "text" }
}Load + validate via parseAgentFile(json). Pass the result to quickRun() or runAgent().
A type: "file" parameter carries only a secret-free format and structure contract. Each host binds its owner's private equivalent and can call checkArtifactCompatibility(parameter, candidate) before ingesting anything. Filenames, rows, prose, image bytes, credentials, memories, and bound values never belong in a shared file.
See the canonical spec page for the full schema with all optional fields.
Grounded source contracts
A source contract declares the evidence an agent requires. The .agent carries that secret-free requirement; each owner privately binds and verifies their own file, folder, provider item, or saved brain snapshot before the agent can run.
When you attach a .klypix in the web builder, AgentMug creates correction-aware grounding from that saved snapshot. It excludes Archive history and cards reversed by saved lifecycle edges or a valid KLYPIX correction overlay. Incomplete projections fail closed.
The authenticated browser hashes the exact selected file bytes; the receipt labels that raw revision owner-client. AgentMug Cloud independently hashes the indexed current-card projection, but does not upload or reparse the original archive bytes. The receipt records both the raw-file revision attestation and evidence digest, plus the card ids and actual read time.
Grounding only — not coordination. A KLYPIX snapshot binding does not call or join brain_sync coordination, peer presence, messages, or file-overlap detection. Saving the original brain again does not update the attachment; attach and verify the new saved revision.
Grounding is private, not local-only: selected card content, card ids, and revision evidence are sent to AgentMug's configured embedding/model processors for the run. They are not put in the shareable .agent or exposed as public source data.
For this source, stale means the snapshot/file revision drifted from its verification pin, or verification expired, before the first model request. It does not mean that a card is old, and it is not derived from brain_doctor.
Adapters — the universality lever
The runtime knows nothing about where it's running. Everything that touches the outside world is an adapter you pass to runAgent():
| Adapter | What it does | Bundled implementations |
|---|---|---|
| LlmClient | Streams messages, returns tokens | AnthropicLlmClient · OpenAiLlmClient · GeminiLlmClient |
| PersistenceAdapter | Creates / updates run records | InMemoryPersistenceAdapter (quickstart) — or write your own (Postgres, SQLite, file) |
| TracingAdapter | Records LLM call telemetry | InMemoryTracingAdapter (with optional hooks) — wrap your OpenTelemetry SDK here |
| TranscriptionAdapter | Audio → text | GeminiTranscriptionAdapter |
| RemindersAdapter | Where reminders land | iCloud CalDAV · local .ics file · or your own |
Swap any layer. The engine doesn't know the difference.
Tools
Tools are normal classes implementing ToolExecutor. Register them with an InMemoryToolRegistry + pass to runAgent() or quickRun().
import {
InMemoryToolRegistry,
gmailSendDefinition,
} from "@agentmug/runtime";
const tools = new InMemoryToolRegistry();
tools.register(gmailSendDefinition, new YourGmailExecutor());The runtime ships built-in tool definitions for: Gmail send, Calendar create-event, Slack send, GitHub create-issue, code execute, web research, web browse, web.fetch_json (generic HTTP), ask_user (pause/resume), memory save/recall/forget, image.generate, invoke_agent, create_reminder, shell.execute (desktop-only), Skills importer.
The web.fetch_json tool is the catalog unlock: any HTTP API becomes a capability without writing a custom executor. See examples/web-research.
Scheduling
Enabled cloud schedules are accepted only when AgentMug can confirm its Redis producer and at least one fleet scheduler worker are ready. Disabled drafts can still be saved, but remain visibly paused instead of appearing active and silently missing their run.
Managed AgentMug
Contact your workspace administrator or AgentMug support. Existing schedule definitions remain saved and paused until service is restored.
Self-hosted
Set REDIS_URL for every API and background-worker replica, restart them, then verify GET /api/schedules/status returns localProducerReady: true and fleetWorkerReady: true before enabling schedules.
Plugins
External npm packages can ship coherent bundles of tools + adapters with the plugin API. definePlugin() builds the bundle; registry.loadPlugin() wires it.
// In your plugin package — e.g. @agentmug-plugins/hackernews
import { definePlugin } from "@agentmug/runtime";
export default definePlugin({
name: "hackernews",
version: "1.0.0",
tools: [
{
definition: hnSearchDefinition,
executor: new HnSearchExecutor(),
},
],
});
// In the consumer
import { InMemoryToolRegistry } from "@agentmug/runtime";
import hnPlugin from "@agentmug-plugins/hackernews";
const tools = new InMemoryToolRegistry();
tools.loadPlugin(hnPlugin);
// every tool the plugin defines is now registeredPlugins can also ship adapter implementations (custom LlmClient, PersistenceAdapter, TracingAdapter) — see the OpenTelemetry adapter package below for the canonical example.
Observability (OpenTelemetry)
@agentmug/otel ships a TracingAdapter that emits LLM-call + transcription spans into your existing OTel pipeline — Honeycomb, Datadog, Tempo, Jaeger, Sentry, anything that consumes OTel.
npm install @agentmug/otel @opentelemetry/api
import { runAgent, noSourcePlan } from "@agentmug/runtime";
import { OtelTracingAdapter } from "@agentmug/otel";
const result = await runAgent({
agentId: "...", userId: "...", userInput: "...",
adapters: {
persistence: yourPersistence,
llm: yourLlmClient,
tracing: new OtelTracingAdapter(), // ← that's it
},
onEvent: () => {},
});Every LLM call becomes a span with attributes like agentmug.llm.provider, agentmug.llm.model, agentmug.llm.tokens, agentmug.llm.cost_cents, agentmug.llm.latency_ms. Wire your existing OTel SDK + exporter as you normally would and runs show up in your dashboards.
Use AgentMug agents from Claude Code / Cursor
@agentmug/mcp-bridge exposes any agent (hosted on agentmug.com or your own backend) as a Model Context Protocol server. Drop into your MCP client config:
{
"mcpServers": {
"email-assistant": {
"command": "npx",
"args": [
"-y",
"@agentmug/mcp-bridge",
"https://agentmug.com/api/external/agents/<AGENT_ID>"
],
"env": { "AGENTMUG_API_KEY": "am_agent_..." }
}
}
}Generate the agent ID + API key from the agent's Deploy → External access tab. Works in Claude Desktop, Claude Code, Cursor (command mode), Continue, Cline.
CLI (agent-controllable)
The agentmug CLI runs .agent files locally AND talks to agentmug.com to create, fork, and invoke agents remotely. Designed to be driven by humans OR by other agents (an LLM with shell access can use it).
# Local — uses your Anthropic key export ANTHROPIC_API_KEY=sk-ant-... agentmug run path/to/my.agent --input "Hello" # Cloud — uses your AgentMug user key export AGENTMUG_API_KEY=am_user_... # mint at /settings/api-keys agentmug create --prompt "Triage my Gmail and draft replies" agentmug list agentmug invoke email-triage --input "Summarize unread" --stream agentmug fork email-triage --as personal-email agentmug key new --agent email-triage
The cloud subcommands hit /api/agents/* and /api/external/agents/:id/invoke. Authenticated via the AGENTMUG_API_KEY env var (a user-levelam_user_… token).
Migrate from raw Anthropic SDK
If you're calling Claude directly from @anthropic-ai/sdk with a system prompt + tool loop, AgentMug is mostly a refactor. The engine + tool registry replace your hand-rolled message loop; your existing tool implementations become ToolExecutor classes.
// Before — raw SDK
const anthropic = new Anthropic({ apiKey });
const messages = [{ role: "user", content: input }];
while (true) {
const r = await anthropic.messages.create({
model, system, messages, tools, max_tokens: 4096,
});
// hand-write: tool_use detection, executor dispatch,
// tool_result formatting, stop_reason loop, etc.
}
// After — @agentmug/runtime
const tools = new InMemoryToolRegistry();
tools.register(gmailSendDefinition, new MyGmailExecutor());
const result = await quickRun({
agentFile: parseAgentFile(myAgentJson),
userInput: input,
llm: { anthropicApiKey: apiKey },
tools,
onEvent: (e) => { /* streaming tokens + tool events */ },
});What you gain by migrating:
- Tool loop with pause/resume, abort, streaming events.
- Provider-agnostic — same code paths against Anthropic, OpenAI, or Gemini by changing the LLM client.
- Portable
.agentJSON files so an agent definition can be version-controlled, forked, or shipped to another runtime (cloud / desktop / CLI / MCP). - Built-in tool catalog you don't have to maintain.
- MCP server adapter so your agents become invocable from any MCP-compatible client without extra code.
Examples
Runnable, in-repo:
Try it without writing any code
Sign up, pick a goal in onboarding, and connect your accounts inline. You get a working agent, then point Claude Code at it with one config file.