Overview
Plugins are the primary way to extend ClarkOS agents. They hook into the tick lifecycle to add custom behavior—posting to social media, fetching data, executing trades, or anything else.Plugin Interface
Every plugin implements this interface:| Property | Required | Description |
|---|---|---|
name | Yes | Unique identifier |
version | Yes | Semver version string |
description | No | Human-readable description |
dependencies | No | Other plugins that must load first |
init() | No | Called once when agent starts |
cleanup() | No | Called when agent stops |
onTick() | No | Called after every tick |
actions | No | Callable functions exposed to agent |
Plugin interface in src/plugins/types.ts
Basic Plugin
Factory Pattern (Recommended)
Use a factory function for configurable plugins:Lifecycle Hooks
init()
Called once when the plugin is registered. Use for setup:- Establish connections
- Validate configuration
- Load initial state
cleanup()
Called when the agent stops. Use for teardown:- Close connections
- Flush buffers
- Save state
onTick()
Called after every tick with full context. Use for reactive behavior:- Check state conditions before acting
- Access memories and knowledge
- Trigger external actions
TickContext in src/core/types.ts
Plugin Actions
Expose callable functions via theactions property:
Plugin Dependencies
Declare dependencies to ensure load order:sortPluginsByDependencies() in src/plugins/loader.ts handles topological sorting
Registering Plugins
Error Handling
Never let plugin errors crash the agent:Testing Plugins
Use theMemoryBackend for testing without a real database:
MemoryBackend in src/backend/memory.ts
Best Practices
- Single responsibility: One plugin, one purpose
- Graceful failures: Log errors, don’t throw
- Respect rate limits: Track API usage, implement cooldowns
- Configurable: Use factory functions with config objects
- Testable: Use dependency injection