OpenCode
Run the OpenCode coding agent inside a VM with skills, MCP servers, and custom configuration.
Quick start
import { agentOS, setup } from "@rivet-dev/agentos";
import opencode from "./software/opencode";
const vm = agentOS({ software: [opencode] });
export const registry = setup({ use: { vm } });
registry.start();
Read Sessions first for session options, streaming events, prompts, and lifecycle management.
LLM Credentials
OpenCode auto-detects a provider when its key is present on the session’s env, sourced from your server’s environment. Common variables:
ANTHROPIC_API_KEY— Anthropic (Claude), the default.OPENAI_API_KEY— OpenAI.OPENROUTER_API_KEY— OpenRouter.GEMINI_API_KEY— Google Gemini.GROQ_API_KEY— Groq.- …plus Amazon Bedrock, Azure, Google Vertex, and 70+ providers via models.dev.
See LLM Credentials, and OpenCode’s providers docs for the full list.
Model configuration
To pin a specific model — or point a provider at a custom endpoint — write an OpenCode config file into the VM before creating the session. OpenCode reads <HOME>/.config/opencode/opencode.json (the agent’s HOME is /home/agentos by default).
Two settings will silently produce an empty response if wrong:
- The Anthropic provider
baseURLmust end in/v1(https://api.anthropic.com/v1). Without/v1, OpenCode calls…/messagesand Anthropic returns404 Not Found. - The
modelmust be a current model id. A retired id returns a404 not_found_errorand the turn ends with zero output.
// Write the config before creating the session
await agent.mkdir("/home/agentos/.config/opencode", { recursive: true });
await agent.writeFile(
"/home/agentos/.config/opencode/opencode.json",
JSON.stringify({
$schema: "https://opencode.ai/config.json",
model: "anthropic/claude-haiku-4-5-20251001", // use a current model id
provider: {
// The Anthropic baseURL MUST include /v1, or requests 404.
anthropic: { options: { baseURL: "https://api.anthropic.com/v1" } },
},
}),
);
const session = await agent.createSession("opencode", {
env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! },
});
Skills
OpenCode discovers SKILL.md files from its skills directory. Write the skill into the VM before creating a session and OpenCode loads it automatically.
const skill = `---
name: commit-style
description: How to write commit messages in this project.
---
Write commit messages in the imperative mood and keep the subject under 50 characters.
`;
// Write the skill before creating the session
await agent.mkdir("/home/agentos/.config/opencode/skills/commit-style");
await agent.writeFile("/home/agentos/.config/opencode/skills/commit-style/SKILL.md", skill);
// OpenCode discovers the skill automatically
const sessionId = await agent.createSession("opencode", {
env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! },
});
MCP servers
Expose extra tools to the agent by passing mcpServers to createSession. Both local child-process servers and remote URLs are supported.
const config = {
mcp: {
filesystem: {
type: "local",
command: ["npx", "-y", "@modelcontextprotocol/server-filesystem", "/home/agentos"],
enabled: true,
},
example: {
type: "remote",
url: "https://mcp.example.com/sse",
headers: { Authorization: "Bearer my-token" },
enabled: true,
},
},
};
await agent.writeFile(
"/home/agentos/.config/opencode/opencode.json",
JSON.stringify(config, null, 2),
);
const sessionId = await agent.createSession("opencode", {
env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! },
});
Pre-install npx-launched servers. A local server started with npx -y … writes install progress to stdout on its first run, which corrupts the MCP stdio handshake (you’ll see Connection closed). Pre-install it in the VM so npx is silent — await agent.exec("npm install -g @modelcontextprotocol/server-filesystem") before the session — or pin the package and point command at the installed binary.
Customizing the agent
OpenCode is a built-in agent, but it’s just a software package under the hood. To ship your own ACP adapter, swap the underlying agent SDK, or register a tweaked build as a new agent, see Custom Agents.