Creating a Plugin
Plugins add content processors and agent tools to EchOS without modifying core code. Each plugin is a separate workspace package inplugins/.
Steps
Write the processor
Create Security rules (non-negotiable):
plugins/my-plugin/src/processor.ts — the logic that fetches/transforms external content:- Always use
validateUrl()before fetching any URL - Always use
sanitizeHtml()on external content - Never use
eval(),Function(), orvm - Never log secrets
Create the agent tool
Create New in this example: AI-powered auto-categorization support using the
plugins/my-plugin/src/tool.ts — defines the tool the LLM agent can call:categorizeContent function from @echos/core. When autoCategorize=true, the plugin will automatically extract category, tags, and optionally gist/summary/key points from the content.PluginContext API
Every plugin receives aPluginContext with:
| Property | Type | Description |
|---|---|---|
sqlite | SqliteStorage | Metadata DB (upsert, query, FTS5 search) |
markdown | MarkdownStorage | Markdown file storage (save, read, delete) |
vectorDb | VectorStorage | Vector embeddings (upsert, search) |
generateEmbedding | (text: string) => Promise<number[]> | Generate embedding vectors |
logger | Logger (Pino) | Structured logger |
config | Record<string, unknown> | App config (API keys, etc.) |
AI Categorization
Plugins can use the built-in categorization service from@echos/core:
- Uses
streamSimple+parseStreamingJsonto stream the LLM response progressively - Fires
onProgressas fields resolve: category → tags → gist (full mode) - Handles errors with safe defaults (fallback to ‘uncategorized’)
- Respects content length limits (5000 chars for lightweight, 10000 for full)
- Is safe to call without
onProgress— callers that don’t need streaming omit the last argument
Existing plugins
| Plugin | Package | Description |
|---|---|---|
| YouTube | @echos/plugin-youtube | Transcript extraction via Python + Whisper fallback |
| Article | @echos/plugin-article | Web article extraction via Readability + DOMPurify |
| Image | @echos/plugin-image | Image storage with metadata extraction (Sharp) |
Image Plugin
The image plugin (@echos/plugin-image) provides the save_image tool for storing and organizing images in the knowledge base.
Features:
- Download images from URLs or accept base64 data
- Extract metadata: dimensions, format, file size, EXIF
- Store original files in
knowledge/image/{category}/ - Create searchable markdown notes with image references
- Optional AI categorization for automatic tagging
- JPEG, PNG, GIF, WebP, AVIF, TIFF, BMP
- Maximum size: 20MB
processImage):
- Validates image format and size
- Extracts metadata using Sharp library
- Generates content-based filename hash
- Returns structured metadata and buffer
- Original file:
knowledge/image/{category}/{hash}.{ext} - Markdown note:
knowledge/note/{category}/{date}-{slug}.md - Embedded reference:

- Automatic photo handler via
bot.on('message:photo') - Downloads from Telegram API
- Passes URL to save_image tool
- Supports captions for context