InkdownInkdown
Start writing

opencode-study

2 files·0 subfolders

Shared Workspace

opencode-study
context-handling
core

context-handling

Shared from "opencode-study" on Inkdown

OpenCode Deep Dive Knowledge Base

A structured knowledge base for understanding OpenCode as a local-first AI coding assistant: architecture, agents, sessions, tools, permissions, database, server design, testing, and extensibility.


How to Use This Knowledge Base

Use this document as a reference when you need to understand:

  • How OpenCode is architected internally.
  • How agents, sub-agents, sessions, tools, and permissions work together.
  • What infrastructure OpenCode uses and deliberately avoids.
  • Where the system can be generalised beyond coding workflows.
  • Which parts are strong, risky, or missing.

Knowledge Base Map

AreaBest starting section
Product overview1. Product Summary
Repository layout2. Repository & Package Structure
Architecture3. Core Architecture
LLM orchestration4. LLM Integration & Orchestration
Agents5. Agent System
Sub-agents6. Sub-Agent Orchestration
Tools7. Tool System
Concurrency8. Parallelism & Resource Model
Human approval9. Human-in-the-Loop Systems
Sessions10. Session Management
Database11. SQLite Database Design
Auth12. Authentication
Server13. Server Architecture
Build and testing14. Build System, 15. Testing Strategy
Security16. Security Model
Missing features17. Explicit Non-Goals / Missing Capabilities
Design philosophy18. Design Philosophy
Generalisation19. Generalising Beyond Coding

Executive Summary

OpenCode is a local-first AI coding assistant for developers. It provides a terminal, web, and desktop interface over a custom agent orchestration system that can inspect code, edit files, run shell commands, call tools, spawn sub-agents, and persist conversation state locally.

The system is notable because its core orchestration is custom-built rather than being based on frameworks such as LangChain, CrewAI, AutoGen, or Vercel AI SDK as the central orchestration layer. External libraries are used for infrastructure and provider transport, but the core model of sessions, agents, tools, permissions, and sub-agent spawning is implemented inside OpenCode.

At a high level:

Text
User Interface
  -> Session
  -> Agent
  -> LLM Provider
  -> Tool Calls
  -> Permission / Question Systems
  -> SQLite Persistence
  -> Events / UI Updates
Key conclusions
  • OpenCode is designed for single-user local development, not multi-tenant production orchestration.
  • The most important abstraction is the session, which isolates conversations, sub-agents, permissions, messages, and state.
  • The most important safety mechanism is permission inheritance, especially for sub-agents.
  • Concurrency uses Effect fibers, not OS-level worker threads.
  • Tool execution and agent orchestration are extensible and domain-agnostic.
  • The coding-specific parts are mostly tools, prompts, agent configurations, and permission names.

Glossary

TermMeaning
AgentA configured AI role with a prompt, model settings, mode, and permission rules.
Primary agentA user-facing agent, such as build, plan, or general.
Sub-agentA helper agent spawned by a parent agent through the task tool.
SessionA conversation unit with its own state, message history, permissions, runner, and optional parent session.
ToolA callable capability exposed to an agent, such as file read, edit, grep, shell, web fetch, or task spawning.
MCPModel Context Protocol, used to connect external tools/providers.
EffectThe functional programming runtime used for services, dependency injection, structured concurrency, and typed effects.
FiberLightweight Effect concurrency primitive running on Node.js's single event loop.
Permission rulesetA rule structure controlling which tools are allowed, denied, or require user approval.
Human-in-the-loopMechanisms that pause execution for user approvals or structured answers.

1. Product Summary

What OpenCode Is

OpenCode is an AI-powered coding assistant for local development. It runs on the developer's machine and gives the LLM access to local codebase context through controlled tools.

Primary Use Cases

  • Codebase exploration and understanding.
  • Writing, editing, and refactoring code.
  • Automating development tasks via shell commands.
  • Planning and architectural reasoning.
  • Delegating exploration or research tasks to sub-agents.
  • Pair programming through terminal, web, or desktop UI.

Target Users

OpenCode is primarily built for:

  • Full-stack developers.
  • Backend engineers.
  • Frontend engineers.
  • DevOps and infrastructure engineers.
  • Open-source contributors.
  • Developers who want AI assistance with local control and permission-based safety.

2. Repository & Package Structure

OpenCode is organised as a monorepo with packages for the core application, shared libraries, SDKs, UI, desktop app, documentation, plugins, and admin console.

Text
opencode/
├── packages/
│   ├── opencode/           # Core business logic, CLI, server
│   │   ├── src/
│   │   │   ├── agent/      # Agent definitions, permissions
│   │   │   ├── session/    # Session management, LLM loop
│   │   │   ├── tool/       # Built-in tool implementations
│   │   │   ├── config/     # Configuration loading
│   │   │   ├── auth/       # Authentication
│   │   │   ├── server/     # HTTP API + WebSocket server
│   │   │   ├── mcp/        # MCP client integration
│   │   │   ├── storage/    # Drizzle ORM + SQLite schemas
│   │   │   ├── permission/ # Permission evaluation engine
│   │   │   ├── question/   # Human-in-loop question system
│   │   │   ├── background/ # Background job system
│   │   │   └── effect/     # Effect utilities
│   │   ├── core/           # Shared utilities
│   │   ├── llm/            # LLM provider abstraction + tool runtime
│   │   ├── sdk/            # JavaScript/TypeScript SDK
│   │   ├── plugin/         # Plugin system
│   │   ├── app/            # Shared SolidJS UI components
│   │   ├── desktop/        # Electron desktop app
│   │   ├── ui/             # UI component library
│   │   ├── web/            # Documentation site
│   │   └── console/        # Admin console
├── script/                 # Build scripts and release automation
└── migration/              # SQLite migration files

Important Package Roles

Package / folderRole
packages/opencodeCore application logic, CLI, server, sessions, tools, auth, config, permissions.
packages/coreShared utilities such as logging, filesystem helpers, and schemas.
packages/llmLLM provider abstraction, route system, and tool runtime.
packages/sdkAPI client for consumers of the HTTP server.
packages/pluginPlugin support and extensibility.
packages/app, packages/uiShared UI components.
packages/desktopElectron desktop application.
packages/webDocumentation website.
migrationSQLite schema migrations.

3. Core Architecture

Architectural Pattern

OpenCode uses a service-oriented architecture built on Effect.

Each feature is modelled as a service with:

PartPurpose
InterfaceDefines what the service can do.
ImplementationDefines how the service behaves.
LayerDefines how dependencies are injected.

This makes the system modular, testable, and dependency-injectable.

Core Services

ServiceResponsibility
SessionManages AI conversations, message history, and state.
AgentDefines AI personalities, modes, prompts, and permissions.
ConfigLoads settings from files, environment variables, and remote configuration.
AuthManages API keys, OAuth, and provider credentials.
ProviderConnects to LLM providers.
ToolExposes file, shell, web, orchestration, and utility capabilities.
ServerProvides HTTP API and WebSocket transport.
PermissionEvaluates and enforces tool access rules.
QuestionHandles structured human-in-the-loop prompts.
BackgroundManages background jobs and task execution.

Main Data Flow

Text
User input
  -> CLI / TUI / Web / Desktop UI
  -> Config loading
  -> Session creation or lookup
  -> Agent selection
  -> LLM call through provider layer
  -> Tool execution when requested
  -> Permission and question checks as needed
  -> Results persisted in SQLite
  -> Events emitted to UI and API consumers

Key Technologies

LayerTechnology
LanguageTypeScript
Functional runtimeEffect
ValidationEffect Schema
UISolidJS
ORMDrizzle ORM
DatabaseSQLite
Runtime and buildBun

4. LLM Integration & Orchestration

Core Insight

OpenCode uses a custom orchestration layer.

The following are implemented internally:

  • Agent management and hierarchy.
  • Session creation and parent-child session relationships.
  • Permission derivation and composition.
  • Sub-agent spawning through the task tool.
  • Tool registry and execution orchestration.
  • LLM route system.
  • Session processor for LLM events, tool calls, and results.

What External Libraries Do

External libraries are used for infrastructure rather than core orchestration.

LibraryRole
EffectFunctional runtime, structured concurrency, dependency injection, typed effects.
Vercel AI SDKOptional provider transport adapter.
DrizzleORM and persistence layer.

Route-Based LLM Abstraction

Location:

Text
packages/llm/src/route/

Conceptual route shape:

TypeScript
Route.make({
  protocol: Protocol,   // API contract, such as OpenAI or Anthropic
  endpoint: Endpoint,   // URL construction
  auth: Auth,           // Bearer tokens, headers, signing
  framing: Framing      // Stream parsing, SSE, event-stream
})

This allows one protocol abstraction to work across multiple providers.

Tool Runtime

Location:

Text
packages/llm/src/tool-runtime.ts

Responsibilities:

  • Executes model-requested tool calls.
  • Handles tool results.
  • Handles tool errors.
  • Integrates tool execution with the route system and session processor.

Tool Definition Pattern

TypeScript
Tool.define(id, Effect.succeed({
  description: string,
  parameters: Schema,
  execute: (args, ctx) => Effect.Effect<ExecuteResult>
}))

Tool Calling Flow

Text
LLM request
  -> Route.compile
  -> Provider API
  -> Tool call event detected
  -> ToolRuntime.execute
  -> Tool.execute through Effect
  -> Tool result returned to session loop
  -> Result fed back to LLM

Runtime Selection

Location:

Text
packages/opencode/src/session/llm.ts

The session layer decides per request between:

RuntimeRole
Native route runtimeCustom Effect-based runtime.
AI SDK runtimeVercel AI SDK-based provider adapter.

5. Agent System

Agent Shape

Agents are configured with a name, mode, permissions, prompt, model, and generation settings.

TypeScript
{
  name: "explore",
  mode: "subagent",
  permission: {
    "*": "deny",
    grep: "allow",
    glob: "allow",
    read: "allow"
  },
  prompt: "You are a fast exploration agent...",
  model: { ... },
  temperature: 0.0
}

Agent Modes

ModeMeaning
primaryUser-facing agent.
subagentHelper agent that can only be invoked by another agent.

Built-In Agents

AgentModePurposeTypical tools
buildPrimaryDefault execution agent.Broad permitted tool set.
planPrimaryPlanning mode.No edit tools.
generalPrimaryMulti-step, parallel work.Broad tool set.
exploreSub-agentFast codebase exploration.grep, glob, read.
scoutSub-agentExternal docs and dependency research.webfetch, websearch.
compactionSub-agentContext compaction.read.
titleSub-agentGenerate session titles.None.
summarySub-agentSummarise sessions.read.

Agent Selection Flow

Text
User input
  -> Session processor
  -> Agent selected from request/config
  -> Agent prompt + available tools prepared
  -> LLM called

6. Sub-Agent Orchestration

How Sub-Agents Are Spawned

Sub-agents are not automatically picked from a worker queue. A parent agent explicitly creates one by calling the task tool.

Example:

TypeScript
task({
  description: "Explore codebase",
  prompt: "Find all API endpoints",
  subagent_type: "explore"
})

This creates a new independent child session.

TypeScript
sessions.create({
  parentID: ctx.sessionID,
  title: description + " (@explore subagent)",
  permission: derivedPermissions
})

Sub-Agent Lifecycle

Text
Parent agent calls task tool
  -> New child session is created
  -> Permissions are derived from parent and sub-agent config
  -> Sub-agent processes its prompt independently
  -> Result is returned to parent as text
  -> Parent may continue, spawn more sub-agents, or resume by task_id

Permission Derivation

Permission inheritance is the critical safety layer.

Location:

Text
packages/opencode/src/agent/subagent-permissions.ts

Permissions are merged roughly as:

Text
Parent agent edit denies
+ Parent session denies
+ Parent external_directory rules
+ Default denies
= Effective sub-agent permissions

Important default denies include todowrite and task unless explicitly allowed.

Safety Rule

A sub-agent should not gain more permissions than its parent.

This prevents permission escalation when an agent delegates work.

Execution Modes

ModeBehaviour
SynchronousParent waits until the sub-agent finishes.
BackgroundSub-agent runs asynchronously and parent continues.
ResumeParent passes task_id to continue an existing sub-agent session.

Limits

There is no hard-coded sub-agent limit in the analysed design. Practical limits come from:

  • LLM provider rate limits.
  • Prompt instructions, such as "launch up to 3 explore agents".
  • User approval prompts.
  • Local system memory and network capacity.

7. Tool System

Tool Sources

OpenCode combines tools from multiple registries.

TypeScript
const tools = yield* Effect.all({
  builtIn: ToolRegistry.builtIn(),
  plugin: ToolRegistry.plugin(),
  skill: ToolRegistry.skill()
})
SourceMeaning
Built-in toolsCore OpenCode tools.
Plugin toolsExternal tools, including MCP integrations.
Skill toolsUser-defined skill tools.

Core Built-In Tools

File Operations
ToolPurpose
readRead file contents with offset and limit.
writeWrite or create files.
editEdit files with diff application.
apply_patchApply git-style patches.
Search
ToolPurpose
grepSearch file contents, typically using ripgrep.
globFind files by pattern.
repo_overviewRetrieve repository structure.
Shell
ToolPurpose
shell / bashExecute shell commands.
repo_cloneClone Git repositories.
Web
ToolPurpose
websearchSearch the web via MCP providers.
webfetchFetch URLs and convert pages into markdown, text, or HTML.
Agent Orchestration
ToolPurpose
taskSpawn sub-agent sessions.
task_statusCheck sub-agent status.
planEnter or exit planning mode.
Interaction
ToolPurpose
questionAsk the user structured questions.
todoRead task lists.
todowriteWrite todo items.
Language Server
ToolPurpose
lspLanguage Server Protocol operations, such as diagnostics or go-to-definition.
Utilities
ToolPurpose
external_directoryAccess directories outside the current project.
skillExecute user-defined skills.
invalidHandle invalid tool calls.

Web Search

Two MCP-based providers are described:

ProviderMCP URLAPI key
Exahttps://mcp.exa.ai/mcpEXA_API_KEY
Parallelhttps://search.parallel.ai/mcpPARALLEL_API_KEY

Selection can be controlled by:

  • OPENCODE_WEBSEARCH_PROVIDER
  • Flags
  • Hash-based random selection using session ID checksum

Default behaviour:

SettingValue
Results8
Live crawlFallback
Timeout25 seconds

Web Fetch

Web fetch is implemented through HTTP requests via Effect's HttpClient, not through a headless browser.

Capabilities include:

  • HTML to Markdown conversion via turndown.
  • HTML parsing via htmlparser2.
  • Cloudflare bot detection retry using honest user-agent fallback.
  • Base64 image attachments.
  • 5 MB response size limit.
  • 30 second default timeout.
  • 120 second maximum timeout.
  • Output formats: markdown, text, html.

Headless Browser Support

OpenCode core does not include Puppeteer, Playwright, or another headless browser.

To add browser automation, use one of:

  • MCP server.
  • Custom tool.
  • Skill plugin.

8. Parallelism & Resource Model

Concurrency Model

OpenCode uses Effect fibers on top of the Node.js event loop.

Text
Node.js event loop
  -> Effect fiber 1
  -> Effect fiber 2
  -> Effect fiber 3

Fibers are lightweight concurrency units. They are not OS threads.

Fibers Compared with async/await

Capabilityasync/awaitEffect fibers
Scoped cleanupManualBuilt in
InterruptionLimitedBuilt in
Controlled concurrencyManualBuilt in
Background jobsManualBuilt in
Structured hierarchyLimitedBuilt in

Example Concurrency Patterns

TypeScript
yield* Effect.all([task1, task2, task3], {
  concurrency: "unbounded"
})
TypeScript
yield* Effect.forEach(tasks, runTask, {
  concurrency: 8
})

CPU Core Usage

Effect fibers do not automatically use more CPU cores. They run on Node.js's single-threaded event loop.

This model is suitable because most OpenCode work is I/O-bound:

  • HTTP calls to LLM providers.
  • File reads.
  • Network fetches.
  • Tool orchestration.

CPU cores would matter more if OpenCode used:

  • Worker threads.
  • Child processes for CPU-bound work.
  • Native parallel execution.

Concurrency Limits

OperationConcurrency
Tool callsUnbounded
File reads8
Grep operations16
Network fetches4
Sequential operations1

Background Job System

Location:

Text
packages/opencode/src/background/job.ts

Conceptual usage:

TypeScript
yield* background.start({
  id: "task-123",
  type: "task",
  run: subagentTask()
})

yield* background.wait({
  id: "task-123"
})

yield* background.cancel("task-123")

Jobs are stored in an in-memory Map, not Redis or a durable queue.

Resource Allocation

OpenCode does not implement explicit resource quotas for sub-agents.

No built-in quota exists for:

  • CPU.
  • Memory.
  • Network.
  • Maximum concurrent sub-agents.
  • Maximum tool calls.

Practical constraints come from:

Constraint sourceExample
ProviderAPI rate limits.
UserPermission approval prompts.
Permission systemDenied tools or denied directories.
Local machineMemory, network, and process limits.

Heavy Sub-Agent Scenario

If a user spawns many heavy sub-agents:

  1. Permission checks may deny unsafe tools.
  2. User approval prompts may multiply.
  3. LLM providers may rate-limit requests.
  4. The local machine may run out of memory or become unstable.

OpenCode is therefore better understood as a local developer assistant than a hardened multi-tenant agent platform.


9. Human-in-the-Loop Systems

OpenCode has two distinct human-in-the-loop systems:

  1. Permission approvals.
  2. Structured questions.

9.1 Permission System

The permission system asks the user to approve or reject tool operations.

Conceptual example:

TypeScript
yield* permission.ask({
  permission: "bash",
  patterns: ["*"],
  metadata: {
    command: "rm -rf /"
  }
})

Possible outcomes:

OutcomeMeaning
onceAllow this single call.
alwaysAllow future matching calls and persist the approval.
rejectDeny the call and reject pending requests for the session.

Permission Rule Examples

TypeScript
{
  bash: "ask",
  edit: "allow",
  task: "deny",
  read: {
    "*.env": "ask",
    "*": "allow"
  }
}
RuleMeaning
askPause and request approval.
allowExecute without asking.
denyBlock execution.
Patterned ruleApply different rules by path or pattern.

Blocking Mechanism

Permission prompts use Effect-based deferred promises.

This means tool execution pauses until the user responds, reducing race conditions and preventing bypass during the blocked state.

9.2 Question System

The question system lets the LLM ask the user structured questions.

Example:

TypeScript
yield* question.ask({
  questions: [{
    question: "Which framework should we use?",
    options: [
      { label: "React", description: "Facebook's library" },
      { label: "Vue", description: "Progressive framework" }
    ],
    multiple: false,
    custom: true
  }]
})

Flow:

Text
LLM calls question tool
  -> UI displays dialog
  -> User responds
  -> Answer is returned to LLM
  -> LLM continues

Reliability Assessment

Overall reliability: 7 / 10

Strengths
  • Blocking via Effect deferred is reliable.
  • always approvals are persisted in SQLite.
  • Session rejection cascades across pending requests.
  • Permission rules can be defined per agent and pattern.
Weaknesses
  • No timeout for abandoned approval prompts.
  • No dedicated permission revocation UI.
  • No "deny forever" option for specific patterns.
  • Complex sub-agent permission inheritance can be hard to audit.
  • No rate limiting on approval prompt spam.

10. Session Management

Location:

Text
packages/opencode/src/session/

Session Responsibilities

Sessions manage:

  • Multi-turn conversation state.
  • Message and part storage.
  • Token usage.
  • Cost calculation.
  • Session forking.
  • Parent-child session hierarchy for sub-agents.
  • Event emission.

Session States

StateMeaning
busyThe LLM or tool loop is processing.
idleThe session is waiting for input.

Stored Token Metrics

Sessions track:

  • Input tokens.
  • Output tokens.
  • Reasoning tokens.
  • Cache read tokens.
  • Cache write tokens.

Event Types

Common emitted events include:

  • Created
  • Updated
  • Deleted
  • Diff
  • Error

Session Independence

Starting a new chat does not automatically cancel existing running sessions.

Each session can have its own runner and may remain busy until it completes or is explicitly cancelled.

Cancellation endpoint:

Text
POST /session/{sessionID}/abort

11. SQLite Database Design

Database Model

OpenCode uses one SQLite database per project.

Typical location:

Text
~/.config/opencode/projects/{projectID}/db.sqlite

There is no Redis, external database, or distributed persistence layer in the core design.

Storage Hierarchy

Text
Session
  -> Message
      -> Part
  -> Todo

Tables

Session Table

Stores chat/session metadata.

Key columns:

ColumnPurpose
idSession ID.
project_idProject association.
parent_idParent session for sub-agent hierarchy.
titleSession title.
agentAgent name.
modelModel metadata.
costCost tracking.
tokens_*Token metrics.
permissionJSON permission rules.
revertJSON revert information.
timestampsCreation/update tracking.

Indexes:

  • project_id
  • workspace_id
  • parent_id
Message Table

Stores user and assistant turns.

Key columns:

ColumnPurpose
idMessage ID.
session_idParent session.
time_createdTimeline ordering.
dataFull JSON message payload.

Primary query optimisation:

Text
(session_id, time_created, id)
Part Table

Stores components of messages.

Part types include:

  • Text.
  • Tool call.
  • Tool result.
  • Reasoning.
  • Error.

Key columns:

ColumnPurpose
idPart ID.
message_idParent message.
session_idParent session.
dataJSON part payload.

Indexes:

  • (message_id, id)
  • session_id
Todo Table

Stores ordered tasks.

Primary key:

Text
(session_id, position)

Columns include:

  • Content.
  • Status.
  • Priority.
  • Position.
  • Timestamps.
Project Table

Stores project metadata:

  • ID.
  • Worktree.
  • Version control system.
  • Name.
  • Icons.
  • Sandboxes.
  • Commands.
  • Timestamps.
Permission Table

Stores project-level permission rules.

  • Primary key: project_id.
  • Rules stored as JSON.
Workspace Table

Stores workspace metadata:

  • ID.
  • Type.
  • Name.
  • Branch.
  • Directory.
  • Extra JSON.
  • Project association.
  • Last-used time.
Account and Account State Tables

Store authentication information:

  • OAuth tokens.
  • Refresh tokens.
  • Expiry.
  • Active account or organisation state.
Session Share Table

Stores session sharing metadata:

  • Share URL.
  • Share ID.
  • Secret.
Event Tables

Event-sourcing support:

TablePurpose
event_sequenceTracks aggregate sequence numbers.
eventStores typed events with aggregate ID, sequence, type, and JSON data.

Database Optimisations

TechniqueBenefit
JSON-mode columnsFlexible typed payloads with automatic parsing.
Cascade deletesCleans up child records.
Integer timestampsCompact and fast comparisons.
Text / ULID primary keysDistributed-friendly IDs.
Composite indexesEfficient timeline and lookup queries.
Foreign keysReferential integrity.
Auto timestampsSimpler lifecycle tracking.
Per-project DBSimple local isolation.

Optimised For

SuitableNot suitable
Single-user local developmentMulti-user concurrent production use
Small-to-medium datasetsMillions of records
Read-heavy chat historyComplex analytical workloads
Session-based queriesDistributed locking or coordination

12. Authentication

Location:

Text
packages/opencode/src/auth/

Supported Methods

  • OAuth.
  • API keys.
  • Well-known auth discovery.

Storage

Credentials are stored in JSON files with 0o600 file permissions, meaning only the local user should be able to read and write them.

Provider-Specific Handling

Each LLM provider has its own auth handler.

This allows providers to differ in:

  • Token format.
  • API key location.
  • OAuth flow.
  • Refresh behaviour.
  • Required headers.

13. Server Architecture

Location:

Text
packages/opencode/src/server/

Server Capabilities

  • HTTP API.
  • OpenAPI specification.
  • WebSocket updates.
  • mDNS local network discovery.
  • Configurable CORS.
  • Graceful shutdown.

Role in the System

The server enables headless operation.

The following clients can consume the same API:

  • TUI.
  • Web UI.
  • Desktop UI.
  • SDK users.

SDK Generation

The SDK in packages/sdk is generated from the OpenAPI specification, keeping API clients aligned with the server contract.


14. Build System

Tooling

OpenCode uses Bun for build and runtime tasks.

Targets

Build output covers 12 platform/architecture combinations:

Text
Linux / macOS / Windows
x
arm64 / x64
x
glibc / musl where applicable

Build Features

  • Cross-platform binary generation.
  • Embedded web UI bundling.
  • Embedded SQLite migrations.
  • Optional source maps.
  • Smoke testing for the current platform.
  • Release automation with GitHub uploads.

15. Testing Strategy

Test Framework

OpenCode uses Bun test.

Test Types

  • Unit tests.
  • Integration tests.
  • CLI tests.
  • HTTP API tests.
  • Effect-specific tests through a testEffect helper.
  • Snapshot tests.

Fixtures and Test Utilities

  • Temporary directories.
  • Test providers.
  • Mock services.
  • Stable snapshot outputs.

Testing Guidance

Documented testing practices include:

  • Avoid arbitrary sleep calls for readiness.
  • Prefer Effect synchronisation primitives.
  • Use dedicated test guides such as:
    • test/AGENTS.md
    • test/EFFECT_TEST_MIGRATION.md

16. Security Model

Strengths

  • Multiple authentication methods.
  • Credentials stored with restricted file permissions.
  • Default-deny permission posture.
  • Per-agent permission isolation.
  • Session-level rejection cascades.
  • Schema-based input validation.
  • Sub-agent permission inheritance.

Risks and Weaknesses

RiskExplanation
API keys in local JSONFile permissions help, but secrets still exist on disk.
No resource quotasSub-agents can consume excessive API/network/local resources.
No permission revocation UIUsers may need to edit config manually.
No approval timeoutExecution can hang forever if the user walks away.
Complex inheritanceSub-agent permission logic may be hard to audit.
No approval spam guardMany tool calls can create many permission prompts.

Security Interpretation

OpenCode is designed for a trusted local developer environment.

It provides meaningful guardrails, especially around tools and permissions, but it is not a hardened multi-user sandbox or production agent execution platform.


17. Explicit Non-Goals / Missing Capabilities

CapabilityStatus
Headless browserNot included.
Redis / external cacheNot used.
Distributed locksNot used.
Durable task queueNot used; background jobs are in-memory.
Resource quotas for sub-agentsNot implemented.
Maximum sub-agent limitNo hard limit.
Permission revocation UINot included.
Approval timeoutNot included.
CPU / OS-thread parallelismNot used for Effect fibers.
Core orchestration frameworkNot based on LangChain, CrewAI, AutoGen, etc.

18. Design Philosophy

1. Local-First and Single-User

OpenCode prioritises local control and developer ownership over multi-tenant cloud orchestration.

2. Trust the Developer

The system assumes the developer is the operator and provides permission controls rather than strict resource policing.

3. Service-Oriented with Effect

Each major capability is a service with interface, implementation, and dependency layer.

Effect provides:

  • Typed error handling.
  • Structured concurrency.
  • Dependency injection.
  • Interruption.
  • Resource safety.

4. Protocol-Agnostic LLM Routing

The LLM layer separates protocol, endpoint, authentication, and stream framing so providers can vary without rewriting orchestration.

5. Tools Are the Extension Point

The orchestration layer is general. Domain-specific behaviour is mainly in:

  • Tool implementations.
  • Agent prompts.
  • Agent configs.
  • Permission rule names.

6. MCP for External Extensibility

MCP is used to connect external services and tools without embedding every capability into core.

7. Sessions Are the Unit of Isolation

Sessions isolate:

  • Message history.
  • Agent state.
  • Parent-child relationships.
  • Permission state.
  • Running jobs.

8. Permission Inheritance Is the Safety Guarantee

Sub-agents inherit constraints from their parent so delegation does not become privilege escalation.


19. Generalising Beyond Coding

Core Claim

OpenCode's harness is mostly domain-agnostic.

The coding-specific parts are:

  • Tool implementations.
  • Agent configurations.
  • Prompts.
  • Permission names and rules.

The reusable parts are:

  • Agent orchestration.
  • Session management.
  • Permission evaluation.
  • Sub-agent spawning.
  • Tool registry.
  • Human-in-the-loop systems.
  • Effect-based concurrency.
  • MCP integration.
  • Background jobs.
  • HTTP server and SDK generation.

Domain Mapping Examples

DomainCustom toolsCustom agents
Research assistantwebsearch, paper_fetch, citation_extract, summary_generateresearcher, writer, analyst
Financial analyststock_query, portfolio_analyze, trade_execute, report_generateanalyst, trader, risk_assessor
Healthcare workflowspatient_query, diagnosis_assist, treatment_planclinician, researcher, reviewer
Marketingcampaign_create, analytics_fetch, content_generatestrategist, copywriter, analyst

Three Generalisation Strategies

1. Fork OpenCode

Keep the core and replace:

  • Tools.
  • Agents.
  • Prompts.
  • Domain-specific permissions.

Best when you want a fast domain-specific fork.

2. Extract a Core Library

Create something like:

Text
@your-org/agent-harness

Then make OpenCode one implementation of that harness.

Best when you want multiple domain applications on the same orchestration core.

3. Template System

Use OpenCode as a scaffold that generates domain-specific configurations.

Best when you want repeatable setup for different teams or use cases.


20. Operational Checklists

Architecture Review Checklist

  • Identify the session lifecycle.
  • Identify primary and sub-agent modes.
  • Review permission rules for each agent.
  • Confirm sub-agents cannot exceed parent permissions.
  • Review tool registry sources.
  • Confirm which tools require user approval.
  • Review database persistence paths.
  • Confirm event flow from backend to UI.
  • Check whether background jobs need durability.
  • Check whether rate limits or quotas are needed.

Security Review Checklist

  • Review credential storage paths and file permissions.
  • Review default permission posture.
  • Audit high-risk tools: shell, write, edit, external directory.
  • Audit sub-agent permission inheritance.
  • Check whether approval prompts can hang indefinitely.
  • Check whether permission revocation is documented.
  • Check whether prompt spam or tool spam can overwhelm users.
  • Decide whether resource quotas are required for your use case.

Generalisation Checklist

  • List domain-specific tools.
  • List domain-specific agents.
  • Define permission names and default policy.
  • Decide which tools require human approval.
  • Decide whether sessions remain the right isolation unit.
  • Decide whether SQLite is sufficient.
  • Decide whether background jobs need durable queues.
  • Decide whether MCP integrations are enough.
  • Define test fixtures for domain-specific workflows.

21. Frequently Asked Questions

Is OpenCode based on LangChain, CrewAI, AutoGen, or a similar orchestration framework?

No. The analysed design indicates that the orchestration layer is custom-built. External libraries are used for infrastructure, provider transport, validation, persistence, and runtime support.

Does OpenCode use a headless browser?

No. Core web fetching uses HTTP requests and parsing. Browser automation would need to be added through MCP, a custom tool, or a skill/plugin.

Do Effect fibers use multiple CPU cores?

No. Effect fibers run on Node.js's single-threaded event loop. They improve structured concurrency and I/O orchestration, but they are not OS threads.

Can sub-agents escalate permissions?

The intended safety model prevents this. Effective sub-agent permissions are derived from parent permissions and additional default denies.

Is the database suitable for production multi-user workloads?

Not as described. The database design is best suited for local, single-user, project-scoped workflows.

What is the most reusable part of OpenCode?

The session + agent + tool + permission harness is the most reusable part. The coding domain can be swapped out by replacing tools, prompts, and agent definitions.


22. Quick Reference

Most Important Concepts

ConceptWhy it matters
SessionUnit of state, isolation, persistence, and execution.
AgentDefines role, tools, prompt, model, and permissions.
ToolPrimary extension mechanism.
Permission inheritanceCore safety model for sub-agent delegation.
Effect fibersStructured concurrency model.
SQLite per projectLocal persistence model.
MCPExternal integration mechanism.

Key Files / Areas to Inspect

AreaPath
Agentspackages/opencode/src/agent/
Sessionspackages/opencode/src/session/
Toolspackages/opencode/src/tool/
LLM routespackages/llm/src/route/
Tool runtimepackages/llm/src/tool-runtime.ts
Permissionspackages/opencode/src/permission/
Sub-agent permissionspackages/opencode/src/agent/subagent-permissions.ts
Questionspackages/opencode/src/question/
Background jobspackages/opencode/src/background/
Database schemapackages/opencode/src/storage/
Serverpackages/opencode/src/server/
Migrationsmigration/

23. Suggested Next Improvements for This Knowledge Base

  • Add links to exact source files once repository URLs are available.
  • Add architecture diagrams for:
    • Session lifecycle.
    • Tool calling loop.
    • Sub-agent permission derivation.
    • Database entity relationships.
  • Add code snippets from actual implementation files.
  • Add a risk register with severity and mitigation.
  • Add a migration guide for extracting the harness into another domain.
  • Add a comparison table against LangChain, CrewAI, AutoGen, and Claude Code-style local assistants.