src
OpenClaw is a self-hosted AI agent platform that connects LLM-powered conversational agents to multiple messaging channels (Telegram, Discord, Slack, Signal, iMessage, LINE, Matrix, Teams, Twitch, IRC, Nostr, Google Chat, Zalo, and more) through a unified gateway architecture. It provides a CLI/TUI for managing agent configuration, model selection, memory, and browser automation, with a WebSocket-based gateway protocol enabling multi-device orchestration including iOS clients via a Swift companion package (Swabble).
Tech Stack
Key Features
- Multi-Channel Messaging
- AI Agent Lifecycle Management
- Auto-Reply Engine
- WebSocket Gateway
- Memory & Semantic Search
- Browser Automation Tools
- Plugin SDK & Extensions
- CLI & TUI
- Canvas Host & A2UI
- Voice Call Integration
- iOS Companion (Swabble)
- Agent Client Protocol (ACP)
Entry Points
Start here when working with this codebase
openclaw.mjsBootstrap and initialize the openclaw runtime by loading compiled distribution files. This is the main process entry point.
Start here when understanding how the application boots, what modules get loaded at startup, or when debugging initialization issues.
tsdown.config.tsConfigure the tsdown bundler with multiple entry points for building different modules. Defines which source files become distributable bundles.
Start here when adding a new module that needs its own build entry point, or when changing how modules are bundled.
vitest.unit.config.tsConfigure unit test discovery and execution patterns for the Vitest test runner.
Start here when adding new test file patterns or configuring test-specific behavior.
vitest.e2e.config.tsDefine E2E-specific Vitest configuration with intelligent worker pool sizing.
Start here when adding end-to-end tests or modifying E2E test infrastructure.
test/setup.tsTest infrastructure setup providing reusable stub plugins and test environment configuration for channel plugin testing.
Start here when writing tests for channel plugins or needing to understand how test stubs are structured.
test/global-setup.tsInitialize test environment and provide cleanup mechanism for test suite teardown.
Start here when modifying global test lifecycle hooks or environment initialization.
test/test-env.tsConfigure process environment for test execution with proper isolation and cleanup.
Start here when tests need specific environment variables or when debugging env-related test failures.
src/canvas-host/server.tsHTTP/WebSocket server for serving canvas static files with live-reload, security checks, and MIME type detection.
Start here when modifying the canvas hosting layer, adding new HTTP routes to the canvas server, or debugging live-reload.
src/canvas-host/a2ui.tsServe A2UI static assets with live reload injection for HTML files.
Start here when modifying how A2UI assets are served or adding new A2UI endpoints.
src/acp/session-mapper.tsMaps session labels/keys to actual session keys via gateway RPC requests. Core session resolution logic.
Start here when modifying session resolution, adding new session-related gateway requests, or debugging session mapping.
extensions/voice-call/index.tsFull extension example with gateway RPC endpoints (voicecall.*) and an LLM tool (voice_call). Demonstrates the extension plugin pattern.
Start here when building a new extension that needs gateway endpoints AND LLM tools. This is the most complete extension reference.
extensions/googlechat/index.tsExtension that handles incoming webhooks from Google Chat. Demonstrates webhook-based extension pattern.
Start here when building an extension that receives webhooks from an external service.
extensions/nostr/index.tsExtension with HTTP handler registration for profile management. Demonstrates REST-style extension endpoints.
Start here when building an extension that exposes HTTP endpoints for external API consumption.
extensions/zalo/index.tsExtension that registers a webhook handler for Zalo messaging platform callbacks.
Start here when building a minimal webhook-receiving extension for a new messaging platform.
scripts/protocol-gen-swift.tsCode generation tool that transpiles protocol schemas to Swift source code for the iOS companion app.
Start here when modifying protocol schemas that need Swift counterparts, or when adding new protocol types.
Swabble/Package.swiftPackage manifest for the Swabble Swift package, orchestrating iOS/macOS project structure and dependencies.
Start here when adding Swift dependencies or modifying the iOS companion app build configuration.
scripts/dev/gateway-smoke.tsDeveloper script that exercises gateway WebSocket endpoints (connect, health, chat.history). Useful as a reference for gateway client usage.
Start here when understanding how to interact with the gateway WebSocket API or when writing gateway integration tests.
scripts/dev/ios-node-e2e.tsEnd-to-end test script for iOS node communication via gateway RPC (connect, health, node.list, node.invoke).
Start here when debugging iOS-to-node communication or understanding the node invocation RPC pattern.
How to Make Changes
Common modification patterns for this codebase
Add a new messaging platform extension (e.g., WhatsApp, WeChat)
extensions/Create a new directory under extensions/ named after your platform (e.g., extensions/whatsapp/)
Pattern: Follow the directory structure of extensions/zalo/ for a minimal webhook-based extension, or extensions/voice-call/index.ts for a full-featured extension with gateway endpoints and LLM tools.
extensions/<platform>/index.tsCreate the main extension entry point that exports a plugin registration function. Register webhook handlers, gateway RPC methods, and/or LLM tools.
Pattern: See extensions/googlechat/index.ts for webhook handler registration pattern. See extensions/voice-call/index.ts for registering gateway RPC endpoints (voicecall.initiate, voicecall.status, etc.) and LLM tools (voice_call).
extensions/<platform>/index.tsImplement message handling: inbound message parsing from the platform's webhook format, and outbound message delivery to the platform's API.
Pattern: See how src/telegram/ handles Telegram-specific message formats, or src/discord/ for Discord message processing. Each channel module has dedicated message handling logic.
src/channels/If this is a first-class channel (not just an extension), register it in the channel plugin system with config and allowlist support.
Pattern: See how src/telegram/, src/discord/, src/slack/, src/signal/, src/imessage/, src/line/, and src/web/ are structured as channel modules. Each has its own directory under src/ with dedicated message handling, monitoring, and delivery logic.
tsdown.config.tsAdd the new extension or channel module as a build entry point so it gets bundled.
Pattern: Look at existing entry points in tsdown.config.ts and add your new module path in the same format.
test/setup.tsAdd test stubs for the new channel plugin if it's a first-class channel.
Pattern: Follow the stub plugin patterns already defined in test/setup.ts for channel plugin testing.
Conventions to follow:
Add a new gateway RPC endpoint
src/gateway/Define the new RPC method in the gateway protocol layer. Add the method name, parameter types, and response types.
Pattern: See how voicecall.initiate, voicecall.continue, voicecall.status etc. are defined in extensions/voice-call/index.ts. Gateway methods use dot-notation namespacing.
src/gateway/Implement the RPC handler that processes the request and returns a response. Include authentication and authorization checks.
Pattern: See how scripts/dev/gateway-smoke.ts calls connect (auth), health (status check), and chat.history (data retrieval) for the client-side pattern. See extensions/voice-call/index.ts for the server-side handler registration pattern.
src/acp/session-mapper.tsIf the endpoint involves session management, integrate with the session mapper. Use the REQUEST pattern for gateway requests.
Pattern: See how sessions.resolve and sessions.reset are defined as gateway requests in src/acp/session-mapper.ts.
scripts/protocol-gen-swift.tsIf the endpoint needs to be callable from iOS, update the Swift protocol generator to emit Swift types for the new RPC method.
Pattern: Follow the existing transpilation patterns in scripts/protocol-gen-swift.ts for converting TypeScript protocol schemas to Swift source code.
test/gateway.multi.e2e.test.tsAdd E2E tests for the new endpoint, especially if it involves multi-instance or node communication.
Pattern: Follow the test patterns in test/gateway.multi.e2e.test.ts for gateway deployment and inter-gateway communication tests.
Conventions to follow:
Add a new LLM tool (agent skill)
src/agents/Define the tool in the agents module. Create the tool schema with name, description, and parameter definitions.
Pattern: See how the voice_call tool is defined in extensions/voice-call/index.ts with action-based dispatch supporting multiple operations (initiate_call, continue_call, speak_to_user, end_call, get_status). Tools use snake_case naming.
src/agents/Implement the tool handler function that executes when the LLM invokes the tool. Handle all action variants and error cases.
Pattern: See extensions/voice-call/index.ts for the action-based dispatch pattern where a single tool (voice_call) handles multiple operations via an 'action' parameter.
src/browser/If the tool involves browser automation, integrate with the Chrome DevTools Protocol automation layer.
Pattern: See src/browser/ for existing browser automation tools and how they use CDP for browser control.
src/memory/If the tool needs to store or retrieve information, integrate with the memory and embeddings system for semantic search.
Pattern: See src/memory/ for vector embeddings storage and semantic search patterns.
Conventions to follow:
Add a new CLI command
src/commands/Create a new command implementation file in the commands module. Define the command's arguments, options, and handler function.
Pattern: See existing command implementations in src/commands/ (agent, doctor, configure, status, onboarding). Each command is a separate module with its own handler.
src/cli/Register the new command in the CLI command registration system. Define the command name, description, aliases, and link it to the handler.
Pattern: See src/cli/ for how existing commands are registered with argument parsing and TUI integration.
src/cli/If the command needs interactive prompts, add TUI components using the interactive prompt system.
Pattern: See src/cli/ for existing TUI and interactive prompt patterns.
Conventions to follow:
Add a new HTTP endpoint to the canvas host server
src/canvas-host/server.tsAdd a new route handler in the canvas host server. Define the HTTP method, path pattern, and handler function.
Pattern: Follow the existing GET /{basePath}/* and HEAD /{basePath}/* patterns in src/canvas-host/server.ts. Note how it handles security checks, MIME type detection, and live-reload injection for HTML files.
src/canvas-host/a2ui.tsIf the endpoint serves A2UI assets, add the route in the A2UI module instead.
Pattern: See how GET /__openclaw__/a2ui/* and HEAD /__openclaw__/a2ui/* are defined in src/canvas-host/a2ui.ts with live reload injection.
src/canvas-host/server.test.tsAdd tests for the new endpoint covering success cases, error cases, and edge cases.
Pattern: Follow the test patterns in src/canvas-host/server.test.ts which tests GET /canvas/, GET /__openclaw__/a2ui/, and WS /canvas/ws endpoints.
Conventions to follow:
Add a new configuration option
src/config/Add the new configuration type/field to the central configuration type definitions.
Pattern: See src/config/ for existing configuration types, paths, and session definitions. Configuration follows a typed schema approach.
src/config/Add default values and validation for the new config option in the config persistence layer.
Pattern: Follow the existing config persistence patterns in src/config/ for how defaults are set and configs are loaded/saved.
src/commands/If the config should be user-settable, add it to the configure command.
Pattern: See the configure command implementation in src/commands/ for how config options are exposed to users.
Conventions to follow:
Add a new agent auth profile or model provider
src/agents/Add the new model provider or auth profile definition in the agents module. Define the provider's API interface, authentication requirements, and model selection logic.
Pattern: See src/agents/ for existing model selection, auth profiles, and provider configurations. The agents module handles AI agent lifecycle including model selection.
src/config/Add configuration types for the new provider's API keys, endpoints, and settings.
Pattern: Follow existing config type patterns in src/config/ for provider-specific settings.
test/provider-timeout.e2e.test.tsAdd timeout and fallback tests for the new provider.
Pattern: Follow the test patterns in test/provider-timeout.e2e.test.ts which tests provider timeout fallback functionality.
scripts/bench-model.tsAdd the new provider to the benchmarking utility so it can be performance-tested.
Pattern: See scripts/bench-model.ts for how LLM API response times are benchmarked across providers.
Conventions to follow:
Add auto-reply logic or modify message processing pipeline
src/auto-reply/Modify the auto-reply orchestration engine. This handles command detection, reply queuing, and streaming.
Pattern: See src/auto-reply/ for the message auto-reply orchestration pipeline including command detection and reply queuing.
src/channels/If the change affects how messages are received from channels, modify the channel plugin system's messaging abstractions.
Pattern: See src/channels/ for the channel plugin system and messaging platform abstractions.
src/web/If the change affects web channel auto-reply specifically, modify the web channel's inbound processing.
Pattern: See src/web/ for web-based messaging channel inbound processing and auto-reply integration.
src/infra/If the change affects outbound message delivery, modify the outbound delivery infrastructure.
Pattern: See src/infra/ for outbound delivery and networking infrastructure.
Conventions to follow:
Coding Conventions
Standards and patterns used in this codebase
Organize source code into domain-specific directories under src/, with each directory representing a bounded context (e.g., agents, gateway, channels, memory). Extensions and third-party integrations live in a separate top-level extensions/ directory.
src/agents/, src/gateway/, src/channels/, src/telegram/, extensions/Use tsdown (tsdown.config.ts) as the build tool with multiple entry points targeting Node.js output. The bootstrap entry point (openclaw.mjs) loads the compiled distribution dynamically.
openclaw.mjs imports and initializes from the compiled dist output defined by tsdown.config.tsMaintain separate Vitest configurations for unit tests and end-to-end tests. A base vitest.config.ts defines shared settings (coverage thresholds, path aliases), while vitest.unit.config.ts and vitest.e2e.config.ts extend it with specific overrides. E2E tests use environment-aware worker settings.
vitest.unit.config.ts extends base config; vitest.e2e.config.ts adds environment-aware workersUse dedicated test setup files: global-setup.ts for environment initialization/cleanup, setup.ts for creating stub channel plugins, and test-env.ts for isolating or using live environment variables. E2E test files follow the naming pattern *.e2e.test.ts.
test/gateway.multi.e2e.test.ts, test/provider-timeout.e2e.test.tsMessaging platforms are implemented as channel plugins with a shared abstraction layer (src/channels) for config, allowlists, and messaging. Each platform (Telegram, Discord, Slack, Signal, iMessage, LINE, Web) has its own src/ directory. Third-party platforms use the extensions/ directory and plugin SDK (src/plugins).
src/channels/ defines the plugin system; src/telegram/, src/discord/, src/slack/ implement specific channels; extensions/ holds Matrix, Teams, Twitch, IRCUse a lightweight .mjs bootstrap file as the main entry point that dynamically loads the compiled distribution, keeping the entry minimal and decoupled from the build output.
openclaw.mjs initializes the runtime and loads the compiled distribution entryThe project is TypeScript-first with path aliases configured in vitest for module resolution. Swift is used for a companion native package (Swabble) managed via Swift Package Manager.
Path aliases defined in vitest.config.ts; Swabble/Package.swift for native Swift targetsUse kebab-case for TypeScript source files and test files. Test files use the suffix .test.ts for unit tests and .e2e.test.ts for end-to-end tests. Configuration files use the pattern tool.config.ts (e.g., vitest.config.ts, tsdown.config.ts).
provider-timeout.e2e.test.ts, gateway.multi.e2e.test.ts, bench-model.ts