docs: add comprehensive documentation structure

Expand the docs/ directory with 109 markdown files covering:

Getting Started:
- Installation guide (binary, source, Docker, Termux)
- Quick start and configuration basics
- First chat tutorial

User Guide:
- Complete CLI reference (9 command docs)
- 11 channel setup guides (Telegram, Discord, Slack, etc.)
- 9 LLM provider guides (OpenRouter, Zhipu, Anthropic, etc.)
- 8 tool documentation files
- Skills system documentation
- Workspace customization guides
- Advanced features (multi-agent, routing, security, etc.)

Developer Guide:
- Architecture and data flow
- Building and testing
- Contributing guidelines
- Extension guides for tools, providers, channels, skills
- API reference for all interfaces

Deployment:
- Docker and systemd guides
- Termux for Android
- SBC guides (Raspberry Pi, LicheeRV Nano, MaixCAM)
- Production security checklist

Operations:
- Health endpoints and monitoring
- Logging and device monitoring
- Troubleshooting guide

Tutorials:
- Step-by-step guides for common use cases
- Hardware control tutorial

Community:
- Project roadmap
- Support channels
- Contributing roles

Includes SUMMARY.md for mdBook/GitBook navigation.

Generated with [Z.ai](https://z.ai/subscribe?ic=JGTYCX7ZO7)

Co-Authored-By: Z.ai GLM-5
This commit is contained in:
Kadic Mirzet 2026-02-19 16:25:40 +01:00
parent 20823bafcc
commit 7263f41cfb
107 changed files with 29690 additions and 0 deletions

190
docs/README.md Normal file
View file

@ -0,0 +1,190 @@
# PicoClaw Documentation
Welcome to the PicoClaw documentation. PicoClaw is an ultra-lightweight AI assistant written in Go that runs on $10 hardware with less than 10MB RAM.
## Why PicoClaw?
| Feature | OpenClaw | NanoBot | PicoClaw |
|---------|----------|---------|----------|
| **Language** | TypeScript | Python | Go |
| **RAM** | >1GB | >100MB | **<10MB** |
| **Startup** | >500s | >30s | **<1s** |
| **Cost** | Mac Mini $599 | ~$50 | **As low as $10** |
## Quick Links
- [Installation](getting-started/installation.md) - Get PicoClaw up and running
- [Quick Start](getting-started/quick-start.md) - Your first conversation in 5 minutes
- [Configuration Reference](configuration/config-file.md) - Complete config options
- [CLI Reference](user-guide/cli-reference.md) - All command-line options
- [Troubleshooting](operations/troubleshooting.md) - Common issues and solutions
## Documentation Sections
### Getting Started
New to PicoClaw? Start here.
- [Installation](getting-started/installation.md) - Install via binary, source, or Docker
- [Quick Start](getting-started/quick-start.md) - 5-minute setup guide
- [Configuration Basics](getting-started/configuration-basics.md) - Essential config concepts
- [Your First Chat](getting-started/first-chat.md) - Running your first conversation
### User Guide
Complete guide to using PicoClaw features.
- [CLI Reference](user-guide/cli-reference.md) - All commands and options
- [onboard](user-guide/cli/onboard.md) - Initialize configuration
- [agent](user-guide/cli/agent.md) - Chat with the agent
- [gateway](user-guide/cli/gateway.md) - Start the gateway
- [status](user-guide/cli/status.md) - System status
- [auth](user-guide/cli/auth.md) - OAuth management
- [cron](user-guide/cli/cron.md) - Scheduled tasks
- [skills](user-guide/cli/skills.md) - Skill management
- [migrate](user-guide/cli/migrate.md) - Migration from OpenClaw
- [Channels](user-guide/channels/README.md) - Chat platform integrations
- [Telegram](user-guide/channels/telegram.md) - Telegram bot setup
- [Discord](user-guide/channels/discord.md) - Discord bot setup
- [Slack](user-guide/channels/slack.md) - Slack integration
- [WhatsApp](user-guide/channels/whatsapp.md) - WhatsApp integration
- [Feishu/Lark](user-guide/channels/feishu-lark.md) - Feishu setup
- [LINE](user-guide/channels/line.md) - LINE bot setup
- [QQ](user-guide/channels/qq.md) - QQ bot setup
- [DingTalk](user-guide/channels/dingtalk.md) - DingTalk setup
- [OneBot](user-guide/channels/onebot.md) - OneBot protocol
- [MaixCam](user-guide/channels/maixcam.md) - MaixCam device
- [Providers](user-guide/providers/README.md) - LLM provider setup
- [OpenRouter](user-guide/providers/openrouter.md) - Multi-model access (recommended)
- [Zhipu/GLM](user-guide/providers/zhipu.md) - Chinese AI models
- [Anthropic](user-guide/providers/anthropic.md) - Claude models
- [OpenAI](user-guide/providers/openai.md) - GPT models
- [Gemini](user-guide/providers/gemini.md) - Google Gemini
- [Groq](user-guide/providers/groq.md) - Fast inference
- [DeepSeek](user-guide/providers/deepseek.md) - DeepSeek models
- [Ollama](user-guide/providers/ollama.md) - Local models
- [vLLM](user-guide/providers/vllm.md) - Self-hosted models
- [Workspace](user-guide/workspace/README.md) - Customizing behavior
- [Structure](user-guide/workspace/structure.md) - Directory layout
- [AGENT.md](user-guide/workspace/agent-md.md) - Agent behavior
- [IDENTITY.md](user-guide/workspace/identity-md.md) - Agent identity
- [Memory](user-guide/workspace/memory.md) - Long-term memory
- [Heartbeat Tasks](user-guide/workspace/heartbeat-tasks.md) - Periodic tasks
- [Tools](user-guide/tools/README.md) - Available tools
- [File System](user-guide/tools/filesystem.md) - read_file, write_file, etc.
- [Exec](user-guide/tools/exec.md) - Shell commands
- [Web](user-guide/tools/web.md) - web_search, web_fetch
- [Messaging](user-guide/tools/messaging.md) - Send messages
- [Spawn](user-guide/tools/spawn.md) - Subagents
- [Cron](user-guide/tools/cron.md) - Scheduled tasks
- [Hardware](user-guide/tools/hardware.md) - I2C, SPI
- [Skills](user-guide/skills/README.md) - Skills system
- [Using Skills](user-guide/skills/using-skills.md)
- [Installing Skills](user-guide/skills/installing-skills.md)
- [Built-in Skills](user-guide/skills/builtin-skills.md)
- [Creating Skills](user-guide/skills/creating-skills.md)
- [Advanced Features](user-guide/advanced/README.md)
- [Multi-Agent System](user-guide/advanced/multi-agent.md)
- [Message Routing](user-guide/advanced/routing.md)
- [Session Management](user-guide/advanced/session-management.md)
- [Model Fallbacks](user-guide/advanced/model-fallbacks.md)
- [Security Sandbox](user-guide/advanced/security-sandbox.md)
- [Environment Variables](user-guide/advanced/environment-variables.md)
- [Voice Transcription](user-guide/advanced/voice-transcription.md)
### Developer Guide
Building and extending PicoClaw.
- [Architecture](developer-guide/architecture.md) - System design
- [Data Flow](developer-guide/data-flow.md) - Message bus architecture
- [Building](developer-guide/building.md) - Build from source
- [Testing](developer-guide/testing.md) - Running tests
- [Contributing](developer-guide/contributing.md) - Contribution guidelines
- [Code Style](developer-guide/code-style.md) - Code standards
#### Extending PicoClaw
- [Creating Tools](developer-guide/extending/creating-tools.md)
- [Creating Providers](developer-guide/extending/creating-providers.md)
- [Creating Channels](developer-guide/extending/creating-channels.md)
- [Creating Skills](developer-guide/extending/creating-skills.md)
#### API Reference
- [Tool Interface](developer-guide/api/tool-interface.md)
- [Provider Interface](developer-guide/api/provider-interface.md)
- [Message Bus](developer-guide/api/message-bus.md)
- [Session API](developer-guide/api/session-api.md)
### Deployment
Deploying PicoClaw in various environments.
- [Docker](deployment/docker.md) - Docker and Docker Compose
- [Systemd](deployment/systemd.md) - Linux service
- [Termux](deployment/termux.md) - Android phones
- [Single-Board Computers](deployment/sbc/README.md)
- [Raspberry Pi](deployment/sbc/rpi.md)
- [LicheeRV Nano](deployment/sbc/licheerv-nano.md)
- [MaixCAM](deployment/sbc/maixcam.md)
- [Security](deployment/security.md) - Production security
### Operations
Running and monitoring PicoClaw.
- [Health Endpoints](operations/health-endpoints.md)
- [Monitoring](operations/monitoring.md)
- [Logging](operations/logging.md)
- [Device Monitoring](operations/device-monitoring.md)
- [Troubleshooting](operations/troubleshooting.md)
### Configuration
Complete configuration reference.
- [Config File](configuration/config-file.md) - config.json reference
- [Agents Config](configuration/agents-config.md)
- [Bindings Config](configuration/bindings-config.md)
- [Channels Config](configuration/channels-config.md)
- [Providers Config](configuration/providers-config.md)
- [Tools Config](configuration/tools-config.md)
- [Gateway Config](configuration/gateway-config.md)
- [Heartbeat Config](configuration/heartbeat-config.md)
- [Devices Config](configuration/devices-config.md)
### Tutorials
Step-by-step guides.
- [Basic Assistant](tutorials/basic-assistant.md) - Beginner setup
- [Telegram Bot](tutorials/telegram-bot.md) - Telegram tutorial
- [Scheduled Tasks](tutorials/scheduled-tasks.md) - Cron and heartbeat
- [Multi-Agent Setup](tutorials/multi-agent-setup.md) - Multiple agents
- [Hardware Control](tutorials/hardware-control.md) - I2C/SPI tutorial
- [Skill Development](tutorials/skill-development.md) - Custom skills
### Community
Join the community.
- [Roadmap](community/roadmap.md) - Project roadmap
- [Support](community/support.md) - Getting help
- [Contributing Roles](community/contributing-roles.md) - Volunteer opportunities
## Getting Help
- **Discord**: [Join our server](https://discord.gg/V4sAZ9XWpN)
- **GitHub Issues**: [Report bugs](https://github.com/sipeed/picoclaw/issues)
- **GitHub Discussions**: [Feature requests](https://github.com/sipeed/picoclaw/discussions)
## Contributing
PRs are welcome! See the [Contributing Guide](developer-guide/contributing.md) for details.

183
docs/SUMMARY.md Normal file
View file

@ -0,0 +1,183 @@
# Summary
[PicoClaw Documentation](README.md)
---
# Getting Started
- [Installation](getting-started/installation.md)
- [Quick Start](getting-started/quick-start.md)
- [Configuration Basics](getting-started/configuration-basics.md)
- [Your First Chat](getting-started/first-chat.md)
---
# User Guide
## CLI Reference
- [CLI Overview](user-guide/cli-reference.md)
- [onboard](user-guide/cli/onboard.md)
- [agent](user-guide/cli/agent.md)
- [gateway](user-guide/cli/gateway.md)
- [status](user-guide/cli/status.md)
- [auth](user-guide/cli/auth.md)
- [cron](user-guide/cli/cron.md)
- [skills](user-guide/cli/skills.md)
- [migrate](user-guide/cli/migrate.md)
## Channels
- [Channels Overview](user-guide/channels/README.md)
- [Telegram](user-guide/channels/telegram.md)
- [Discord](user-guide/channels/discord.md)
- [Slack](user-guide/channels/slack.md)
- [WhatsApp](user-guide/channels/whatsapp.md)
- [Feishu/Lark](user-guide/channels/feishu-lark.md)
- [LINE](user-guide/channels/line.md)
- [QQ](user-guide/channels/qq.md)
- [DingTalk](user-guide/channels/dingtalk.md)
- [OneBot](user-guide/channels/onebot.md)
- [MaixCam](user-guide/channels/maixcam.md)
## Providers
- [Providers Overview](user-guide/providers/README.md)
- [OpenRouter](user-guide/providers/openrouter.md)
- [Zhipu/GLM](user-guide/providers/zhipu.md)
- [Anthropic](user-guide/providers/anthropic.md)
- [OpenAI](user-guide/providers/openai.md)
- [Gemini](user-guide/providers/gemini.md)
- [Groq](user-guide/providers/groq.md)
- [DeepSeek](user-guide/providers/deepseek.md)
- [Ollama](user-guide/providers/ollama.md)
- [vLLM](user-guide/providers/vllm.md)
## Workspace
- [Workspace Overview](user-guide/workspace/README.md)
- [Directory Structure](user-guide/workspace/structure.md)
- [AGENT.md](user-guide/workspace/agent-md.md)
- [IDENTITY.md](user-guide/workspace/identity-md.md)
- [Memory](user-guide/workspace/memory.md)
- [Heartbeat Tasks](user-guide/workspace/heartbeat-tasks.md)
## Tools
- [Tools Overview](user-guide/tools/README.md)
- [File System](user-guide/tools/filesystem.md)
- [Exec](user-guide/tools/exec.md)
- [Web](user-guide/tools/web.md)
- [Messaging](user-guide/tools/messaging.md)
- [Spawn](user-guide/tools/spawn.md)
- [Cron](user-guide/tools/cron.md)
- [Hardware](user-guide/tools/hardware.md)
## Skills
- [Skills Overview](user-guide/skills/README.md)
- [Using Skills](user-guide/skills/using-skills.md)
- [Installing Skills](user-guide/skills/installing-skills.md)
- [Built-in Skills](user-guide/skills/builtin-skills.md)
- [Creating Skills](user-guide/skills/creating-skills.md)
## Advanced Features
- [Advanced Overview](user-guide/advanced/README.md)
- [Multi-Agent System](user-guide/advanced/multi-agent.md)
- [Message Routing](user-guide/advanced/routing.md)
- [Session Management](user-guide/advanced/session-management.md)
- [Model Fallbacks](user-guide/advanced/model-fallbacks.md)
- [Security Sandbox](user-guide/advanced/security-sandbox.md)
- [Environment Variables](user-guide/advanced/environment-variables.md)
- [Voice Transcription](user-guide/advanced/voice-transcription.md)
---
# Configuration
- [Config File Reference](configuration/config-file.md)
- [Agents Configuration](configuration/agents-config.md)
- [Bindings Configuration](configuration/bindings-config.md)
- [Channels Configuration](configuration/channels-config.md)
- [Providers Configuration](configuration/providers-config.md)
- [Tools Configuration](configuration/tools-config.md)
- [Gateway Configuration](configuration/gateway-config.md)
- [Heartbeat Configuration](configuration/heartbeat-config.md)
- [Devices Configuration](configuration/devices-config.md)
---
# Operations
- [Health Endpoints](operations/health-endpoints.md)
- [Monitoring](operations/monitoring.md)
- [Logging](operations/logging.md)
- [Device Monitoring](operations/device-monitoring.md)
- [Troubleshooting](operations/troubleshooting.md)
---
# Tutorials
- [Tutorials Overview](tutorials/README.md)
- [Basic Assistant Setup](tutorials/basic-assistant.md)
- [Telegram Bot](tutorials/telegram-bot.md)
- [Scheduled Tasks](tutorials/scheduled-tasks.md)
- [Multi-Agent Setup](tutorials/multi-agent-setup.md)
- [Hardware Control](tutorials/hardware-control.md)
- [Skill Development](tutorials/skill-development.md)
---
# Deployment
- [Docker](deployment/docker.md)
- [Systemd](deployment/systemd.md)
- [Termux (Android)](deployment/termux.md)
## Single-Board Computers
- [SBC Overview](deployment/sbc/README.md)
- [Raspberry Pi](deployment/sbc/rpi.md)
- [LicheeRV Nano](deployment/sbc/licheerv-nano.md)
- [MaixCAM](deployment/sbc/maixcam.md)
## Security
- [Security Configuration](deployment/security.md)
---
# Developer Guide
- [Architecture](developer-guide/architecture.md)
- [Data Flow](developer-guide/data-flow.md)
- [Building](developer-guide/building.md)
- [Testing](developer-guide/testing.md)
- [Contributing](developer-guide/contributing.md)
- [Code Style](developer-guide/code-style.md)
## Extending PicoClaw
- [Creating Tools](developer-guide/extending/creating-tools.md)
- [Creating Providers](developer-guide/extending/creating-providers.md)
- [Creating Channels](developer-guide/extending/creating-channels.md)
- [Creating Skills](developer-guide/extending/creating-skills.md)
## API Reference
- [Tool Interface](developer-guide/api/tool-interface.md)
- [Provider Interface](developer-guide/api/provider-interface.md)
- [Message Bus](developer-guide/api/message-bus.md)
- [Session API](developer-guide/api/session-api.md)
---
# Community
- [Community Overview](community/README.md)
- [Project Roadmap](community/roadmap.md)
- [Getting Help](community/support.md)
- [Contributing Roles](community/contributing-roles.md)

132
docs/community/README.md Normal file
View file

@ -0,0 +1,132 @@
# Community
Welcome to the PicoClaw community! This section covers how to get involved, get help, and contribute to the project.
## Quick Links
| Resource | Link |
|----------|------|
| Discord | [Join our server](https://discord.gg/V4sAZ9XWpN) |
| GitHub | [github.com/sipeed/picoclaw](https://github.com/sipeed/picoclaw) |
| Issues | [Report bugs](https://github.com/sipeed/picoclaw/issues) |
| Discussions | [Feature requests](https://github.com/sipeed/picoclaw/discussions) |
## Community Sections
### [Roadmap](roadmap.md)
See what's planned for PicoClaw's future development. The roadmap covers:
- Core optimization goals
- Security hardening plans
- New connectivity features
- Advanced capabilities
- Developer experience improvements
### [Support](support.md)
Get help when you need it:
- Frequently asked questions
- Troubleshooting resources
- How to ask good questions
- Community support channels
### [Contributing Roles](contributing-roles.md)
Find your place in the community:
- Ways to contribute
- Volunteer opportunities
- Recognition program
- Getting started guide
## Getting Started
### New to PicoClaw?
1. Read the [Installation Guide](../getting-started/installation.md)
2. Follow the [Quick Start](../getting-started/quick-start.md)
3. Try the [Basic Assistant Tutorial](../tutorials/basic-assistant.md)
### Need Help?
1. Check the [Troubleshooting Guide](../operations/troubleshooting.md)
2. Search [existing issues](https://github.com/sipeed/picoclaw/issues)
3. Ask in [GitHub Discussions](https://github.com/sipeed/picoclaw/discussions)
4. Join our [Discord](https://discord.gg/V4sAZ9XWpN)
### Want to Contribute?
1. Read the [Contributing Guide](../developer-guide/contributing.md)
2. Check [open issues](https://github.com/sipeed/picoclaw/issues)
3. Look at [good first issues](https://github.com/sipeed/picoclaw/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22)
4. Review the [Contributing Roles](contributing-roles.md)
## Community Guidelines
### Be Respectful
- Treat everyone with respect
- Welcome newcomers
- Be patient with questions
- Provide constructive feedback
### Be Helpful
- Share your knowledge
- Help test new features
- Report bugs with details
- Improve documentation
### Be Collaborative
- Discuss before major changes
- Follow the code of conduct
- Give credit where due
- Build on each other's work
## Stay Updated
### Release Announcements
Watch the GitHub repository for release notifications:
1. Go to [github.com/sipeed/picoclaw](https://github.com/sipeed/picoclaw)
2. Click "Watch" → "Releases only"
### Blog and News
Check for updates on:
- GitHub Discussions announcements
- Discord #announcements channel
## Code of Conduct
All community members are expected to follow our code of conduct:
- Be inclusive and welcoming
- Be respectful of differing viewpoints
- Accept constructive criticism gracefully
- Focus on what is best for the community
- Show empathy towards other community members
## Recognition
We recognize contributors through:
- GitHub contributor statistics
- Release notes acknowledgments
- Community spotlight in Discord
- Contributor badges
## Contact
- **Bug reports**: [GitHub Issues](https://github.com/sipeed/picoclaw/issues)
- **Feature requests**: [GitHub Discussions](https://github.com/sipeed/picoclaw/discussions)
- **General questions**: [Discord](https://discord.gg/V4sAZ9XWpN)
- **Security issues**: See [Security Policy](https://github.com/sipeed/picoclaw/security/policy)
## Thank You
Thank you for being part of the PicoClaw community! Your participation makes the project better for everyone.

View file

@ -0,0 +1,318 @@
# Contributing Roles
This guide describes the various ways you can contribute to PicoClaw and the volunteer roles available.
## Ways to Contribute
### Code Contributions
Write code to improve PicoClaw:
- Fix bugs
- Add features
- Improve performance
- Refactor code
See [Contributing Guide](../developer-guide/contributing.md) for details.
### Documentation
Help improve documentation:
- Fix typos and errors
- Add examples and tutorials
- Translate documentation
- Write API references
### Community Support
Help other users:
- Answer questions on Discord
- Respond to GitHub Discussions
- Review issues and provide solutions
- Share your knowledge
### Testing
Improve quality:
- Test new releases
- Report bugs
- Verify fixes
- Test on different platforms
### Skill Development
Extend PicoClaw's capabilities:
- Create custom skills
- Share skills with the community
- Improve existing skills
## Volunteer Roles
### Contributor
Anyone who makes contributions to the project.
**Requirements:**
- One or more merged PRs, or
- Significant documentation improvements, or
- Active community support
**Benefits:**
- Listed in contributors file
- Acknowledged in release notes
### Maintainer
Regular contributors who help maintain the project.
**Responsibilities:**
- Review pull requests
- Triage issues
- Help with releases
- Guide new contributors
**Requirements:**
- Consistent contributions over time
- Good understanding of the codebase
- Positive community interactions
**Benefits:**
- Write access to repository
- Input on project direction
- Recognition as maintainer
### Documentation Lead
Focus on documentation quality and coverage.
**Responsibilities:**
- Review documentation PRs
- Plan documentation improvements
- Write guides and tutorials
- Maintain documentation structure
**Requirements:**
- Strong writing skills
- Understanding of PicoClaw features
- Attention to detail
### Community Moderator
Help manage community interactions.
**Responsibilities:**
- Moderate Discord server
- Welcome new members
- Keep discussions productive
- Escalate issues appropriately
**Requirements:**
- Active in community
- Good communication skills
- Fair and patient
### Skill Curator
Manage the skill ecosystem.
**Responsibilities:**
- Review community skills
- Maintain skill registry
- Create example skills
- Help skill developers
**Requirements:**
- Understanding of skill system
- Creative problem-solving
- Good documentation
### Platform Specialist
Expert for specific platforms.
**Responsibilities:**
- Test on your platform
- Report platform-specific issues
- Help users on your platform
- Maintain platform documentation
**Platforms:**
- Raspberry Pi
- LicheeRV Nano
- MaixCAM
- Android/Termux
- Windows
- macOS
### Channel Specialist
Expert for specific chat platforms.
**Responsibilities:**
- Test channel integrations
- Help users set up channels
- Report channel issues
- Improve channel documentation
**Channels:**
- Telegram
- Discord
- Slack
- WhatsApp
- QQ
- LINE
- Feishu/Lark
- DingTalk
### Language Ambassador
Help with translations and localization.
**Responsibilities:**
- Translate documentation
- Help users in your language
- Review translations
- Identify localization needs
**Languages:**
- Chinese (Simplified)
- Chinese (Traditional)
- Japanese
- Korean
- German
- French
- Spanish
- Others welcome!
## Getting Started
### 1. Choose Your Path
Based on your interests and skills:
| Interest | Role |
|----------|------|
| Writing code | Contributor, Maintainer |
| Writing docs | Documentation Lead |
| Helping people | Community Moderator, Support |
| Testing | Platform Specialist |
| Creating content | Skill Curator |
| Languages | Language Ambassador |
### 2. Start Contributing
1. **Read the Contributing Guide**
- [Contributing Guide](../developer-guide/contributing.md)
- [Code of Conduct](#code-of-conduct)
2. **Find a Task**
- [Good First Issues](https://github.com/sipeed/picoclaw/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22)
- [Help Wanted](https://github.com/sipeed/picoclaw/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22)
- [Documentation Issues](https://github.com/sipeed/picoclaw/issues?q=is%3Aopen+is%3Aissue+label%3Adocumentation)
3. **Join the Community**
- [Discord](https://discord.gg/V4sAZ9XWpN)
- [GitHub Discussions](https://github.com/sipeed/picoclaw/discussions)
4. **Make Your First Contribution**
- Submit a PR
- Help someone with a question
- Improve documentation
### 3. Get Recognized
Contributors are recognized through:
- GitHub contributor statistics
- Release notes acknowledgments
- Community highlights
- Role badges in Discord
## Recognition Program
### Contribution Levels
| Level | Requirement | Recognition |
|-------|-------------|-------------|
| First Timer | First merged PR | Welcome message, contributor badge |
| Regular | 5+ merged PRs | Listed in CONTRIBUTORS file |
| Core | 20+ merged PRs | Invitation to maintainer role |
### Special Recognition
- **Monthly Spotlight**: Featured contributor in Discord
- **Release Hero**: Major contributor to a release
- **Community Hero**: Exceptional community support
- **Doc Champion**: Significant documentation improvements
## Expectations
### For All Contributors
- Follow the code of conduct
- Be respectful and constructive
- Focus on what's best for the project
- Accept feedback gracefully
- Help others when you can
### For Maintainers
- Be responsive to issues and PRs
- Provide clear feedback
- Help new contributors
- Maintain code quality
- Document decisions
## Code of Conduct
### Our Standards
- Be respectful and inclusive
- Welcome diverse perspectives
- Accept constructive criticism
- Focus on constructive discussions
- Show empathy towards others
### Unacceptable Behavior
- Harassment or discrimination
- Trolling or insulting comments
- Publishing others' private information
- Any unprofessional conduct
### Enforcement
Report issues to maintainers via:
- GitHub private messages
- Discord DM to moderators
## Questions?
### About Contributing
- Ask in [GitHub Discussions](https://github.com/sipeed/picoclaw/discussions)
- Join [Discord](https://discord.gg/V4sAZ9XWpN) `#contributors` channel
### About Roles
- Review the requirements above
- Talk to current maintainers
- Start contributing in that area
## Thank You!
Every contribution matters, whether it's:
- A typo fix in documentation
- A bug report with details
- Helping a new user
- Writing a major feature
Thank you for making PicoClaw better!
---
*Ready to contribute? Start with [Good First Issues](https://github.com/sipeed/picoclaw/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22).*

183
docs/community/roadmap.md Normal file
View file

@ -0,0 +1,183 @@
# Project Roadmap
This document outlines the development roadmap for PicoClaw. For the most up-to-date information, see [ROADMAP.md](../../ROADMAP.md) in the repository.
## Vision
To build the ultimate lightweight, secure, and fully autonomous AI Agent infrastructure - automate the mundane, unleash your creativity.
## Core Pillars
### 1. Core Optimization: Extreme Lightweight
Our defining characteristic. We fight software bloat to ensure PicoClaw runs smoothly on the smallest embedded devices.
**Goals:**
- Run smoothly on 64MB RAM embedded boards (e.g., low-end RISC-V SBCs)
- Core process consuming < 20MB RAM
- Startup time < 1 second
**Current Status:**
- Memory footprint significantly lower than alternatives
- Fast startup achieved
- Continuous optimization in progress
### 2. Security Hardening: Defense in Depth
Building a "Secure-by-Default" agent.
**Focus Areas:**
- **Input Defense & Permission Control**
- Prompt injection defense
- Tool abuse prevention
- SSRF protection with built-in blocklists
- **Sandboxing & Isolation**
- Filesystem sandbox for file operations
- Context isolation between sessions
- Privacy redaction for sensitive data
- **Authentication & Secrets**
- Modern cryptography (ChaCha20-Poly1305)
- OAuth 2.0 flows for providers
### 3. Connectivity: Protocol-First Architecture
Connect every model, reach every platform.
**Provider Support:**
- Architecture upgrade to protocol-based classification
- Local model integration (Ollama, vLLM, LM Studio)
- Continued support for frontier closed-source models
**Channel Support:**
- IM platforms: QQ, WeChat, DingTalk, Feishu, Telegram, Discord, WhatsApp, LINE, Slack, Email, and more
- OneBot protocol support
- Native attachment handling
**Skill Marketplace:**
- Skill discovery and installation
- Community skill sharing
### 4. Advanced Capabilities: From Chatbot to Agentic AI
Beyond conversation - focusing on action and collaboration.
**Operations:**
- MCP (Model Context Protocol) support
- Browser automation via CDP
- Mobile device control
**Multi-Agent Collaboration:**
- Basic multi-agent implementation
- Smart model routing
- Swarm mode for multi-instance collaboration
- AI-Native OS interaction paradigms
### 5. Developer Experience & Documentation
Lowering the barrier to entry so anyone can deploy in minutes.
**Goals:**
- Zero-config quick start with interactive CLI wizard
- Comprehensive platform guides (Windows, macOS, Linux, Android)
- Step-by-step tutorials for all features
- AI-assisted documentation generation
### 6. Engineering: AI-Powered Open Source
Using AI to accelerate development.
- AI-enhanced CI/CD (code review, linting, PR labeling)
- Bot noise reduction
- AI-powered issue triage
### 7. Brand & Community
**Logo Design:** We are looking for a Mantis Shrimp (Stomatopoda) logo design!
- Concept: "Small but Mighty" and "Lightning Fast Strikes"
## Release Timeline
### Short Term (Next 3 Months)
- [ ] Complete protocol-based provider architecture
- [ ] Enhanced documentation and tutorials
- [ ] Additional channel integrations
- [ ] Performance optimizations
### Medium Term (3-6 Months)
- [ ] MCP support implementation
- [ ] Multi-agent collaboration improvements
- [ ] Skill marketplace launch
- [ ] Mobile operation support
### Long Term (6-12 Months)
- [ ] Browser automation
- [ ] Swarm mode
- [ ] AI-Native OS exploration
- [ ] Expanded hardware support
## Contributing to the Roadmap
We welcome community contributions to any item on this roadmap!
### How to Contribute
1. **Comment on Issues**: Find relevant issues on [GitHub](https://github.com/sipeed/picoclaw/issues)
2. **Submit PRs**: Implement features and submit pull requests
3. **Provide Feedback**: Share your use cases and requirements
4. **Test Early Builds**: Help test new features before release
### Suggesting Features
1. Check existing issues first
2. Open a [GitHub Discussion](https://github.com/sipeed/picoclaw/discussions) for discussion
3. Provide detailed use cases
4. Be open to feedback and iteration
## Tracking Progress
- **GitHub Projects**: Track specific initiatives
- **Milestones**: See planned releases
- **Changelog**: View completed features
## Prioritization
Features are prioritized based on:
1. **Community demand**: User requests and feedback
2. **Strategic alignment**: Fit with vision and goals
3. **Resource availability**: Contributor capacity
4. **Dependencies**: Technical requirements
## Version History
| Version | Highlights |
|---------|------------|
| 1.x | Core functionality, multi-provider, multi-channel |
| Upcoming | Protocol architecture, enhanced docs, more integrations |
## Get Involved
Ready to help build the best Edge AI Agent?
- [View Open Issues](https://github.com/sipeed/picoclaw/issues)
- [Join Discord](https://discord.gg/V4sAZ9XWpN)
- [Contribute Code](../developer-guide/contributing.md)
---
*This roadmap is subject to change based on community feedback and technical requirements. Last updated: 2024.*

287
docs/community/support.md Normal file
View file

@ -0,0 +1,287 @@
# Getting Help
This guide covers how to get help with PicoClaw.
## Quick Help
### Common Issues
| Issue | Solution |
|-------|----------|
| Command not found | Add binary to PATH or use full path |
| No API key | Add provider API key to config |
| Permission denied | Check file permissions |
| Rate limited | Wait or set up fallback models |
See [Troubleshooting](../operations/troubleshooting.md) for more solutions.
## Documentation
### Start Here
1. [Installation Guide](../getting-started/installation.md)
2. [Quick Start](../getting-started/quick-start.md)
3. [Configuration Basics](../getting-started/configuration-basics.md)
### Reference
- [CLI Reference](../user-guide/cli-reference.md)
- [Configuration Reference](../configuration/config-file.md)
- [Tools Overview](../user-guide/tools/README.md)
### Tutorials
- [Basic Assistant](../tutorials/basic-assistant.md)
- [Telegram Bot](../tutorials/telegram-bot.md)
- [Scheduled Tasks](../tutorials/scheduled-tasks.md)
## Community Support
### Discord
Join our Discord server for real-time help:
[https://discord.gg/V4sAZ9XWpN](https://discord.gg/V4sAZ9XWpN)
**Channels:**
- `#general` - General discussion
- `#help` - Get help with issues
- `#showcase` - Share your projects
- `#announcements` - Project updates
### GitHub Discussions
For longer-form questions and feature discussions:
[https://github.com/sipeed/picoclaw/discussions](https://github.com/sipeed/picoclaw/discussions)
**Categories:**
- Q&A - Questions and answers
- Ideas - Feature suggestions
- Show and Tell - Project showcases
- General - Other discussions
## Reporting Issues
### Before Reporting
1. **Search existing issues** - Your problem may already be reported
2. **Check documentation** - Review relevant docs
3. **Try debug mode** - Run with `--debug` flag
4. **Update PicoClaw** - Ensure you're on the latest version
### How to Report
Open an issue at: [https://github.com/sipeed/picoclaw/issues](https://github.com/sipeed/picoclaw/issues)
### Issue Template
```markdown
## Description
Brief description of the problem
## Steps to Reproduce
1. Run command `picoclaw ...`
2. See error
## Expected Behavior
What should happen
## Actual Behavior
What actually happens
## Environment
- PicoClaw version: [run `picoclaw version`]
- OS: [e.g., Ubuntu 22.04, macOS 14]
- Architecture: [e.g., amd64, arm64]
## Debug Output
```
[paste debug output here, redact sensitive info]
```
## Additional Context
Any other relevant information
```
### What to Include
**Always Include:**
- PicoClaw version
- Operating system
- Steps to reproduce
- Error messages
**If Relevant:**
- Configuration file (redact API keys)
- Debug output
- Logs (redact sensitive info)
- Screenshots
### Redacting Sensitive Information
Before sharing logs or config:
```bash
# Redact API keys
sed -i 's/sk-[a-zA-Z0-9-]*/sk-***/g' config.json
# Redact tokens
sed -i 's/[0-9]\{10,\}:AAH[a-zA-Z0-9_-]*/TOKEN/g' log.txt
```
## Asking Good Questions
### Be Specific
```
Bad: "It doesn't work"
Good: "When I run `picoclaw agent -m 'hello'`, I get 'no API key configured' error"
```
### Provide Context
```
Bad: "How do I use Telegram?"
Good: "I'm trying to set up a Telegram bot. I've created the bot with BotFather and got the token. How do I configure it in PicoClaw?"
```
### Show Your Work
```
Bad: "The config is wrong"
Good: "Here's my config.json:
{
"providers": {
"openrouter": {
"api_key": "sk-or-v1-***"
}
}
}
And I'm getting error: 'model not found'"
```
### One Issue at a Time
Focus on one problem per question or issue. This makes it easier to help and for others to find solutions later.
## Response Times
| Channel | Typical Response |
|---------|------------------|
| GitHub Issues | 1-3 days |
| GitHub Discussions | 1-3 days |
| Discord | Minutes to hours |
Response times vary based on complexity, timezone, and community availability.
## Self-Help Resources
### Debug Mode
Enable detailed logging:
```bash
picoclaw agent --debug -m "your message"
picoclaw gateway --debug
```
### Check Configuration
```bash
# Validate JSON syntax
cat ~/.picoclaw/config.json | python3 -m json.tool
# Check config is loaded
picoclaw status
```
### Check Logs
```bash
# If logging to file
tail -f /var/log/picoclaw/app.log
# Systemd journal
journalctl -u picoclaw -f
```
### Test Components
```bash
# Test provider connection
picoclaw agent -m "Hello"
# Test channel
picoclaw gateway --debug
# Check status
picoclaw status
```
## Security Issues
For security vulnerabilities:
1. **Do not** open a public issue
2. Email security concerns privately
3. Allow time for response before disclosure
4. See [Security Policy](https://github.com/sipeed/picoclaw/security/policy)
## Feature Requests
For feature suggestions:
1. Check [existing discussions](https://github.com/sipeed/picoclaw/discussions/categories/ideas)
2. Open a new discussion with "Idea" category
3. Describe the use case
4. Explain the expected benefit
## Commercial Support
For enterprise or commercial support needs, contact the maintainers through GitHub.
## FAQ
### General Questions
**Q: Is PicoClaw free?**
A: Yes, PicoClaw is open source under the MIT license. You need an LLM provider API key which may have costs.
**Q: What's the difference between PicoClaw and OpenClaw?**
A: PicoClaw is written in Go, optimized for minimal resource usage (<10MB RAM vs >1GB for OpenClaw).
**Q: Can I run PicoClaw on a Raspberry Pi?**
A: Yes! PicoClaw is designed for embedded and low-resource environments.
### Technical Questions
**Q: Which provider should I use?**
A: OpenRouter is recommended for most users - it provides access to many models with a free tier.
**Q: How do I update PicoClaw?**
A: Download the latest binary and replace the old one.
**Q: Where are my conversations stored?**
A: In `~/.picoclaw/workspace/sessions/` as JSON files.
## Still Need Help?
If you've tried everything and still need help:
1. Open a [GitHub Issue](https://github.com/sipeed/picoclaw/issues) with full details
2. Join [Discord](https://discord.gg/V4sAZ9XWpN) and ask in `#help`
3. Start a [GitHub Discussion](https://github.com/sipeed/picoclaw/discussions)
We're here to help!

View file

@ -0,0 +1,550 @@
# Configuration File Reference
The main configuration file is located at `~/.picoclaw/config.json`. This page provides a complete reference for all configuration options.
## Configuration File Location
```
~/.picoclaw/config.json
```
Use `picoclaw onboard` to create a default configuration file.
## Configuration Structure
```json
{
"agents": { ... },
"bindings": [ ... ],
"session": { ... },
"channels": { ... },
"providers": { ... },
"gateway": { ... },
"tools": { ... },
"heartbeat": { ... },
"devices": { ... }
}
```
## Agents Configuration
Configure agent behavior and model settings.
### agents.defaults
Default settings for all agents.
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `workspace` | string | `~/.picoclaw/workspace` | Working directory for the agent |
| `restrict_to_workspace` | bool | `true` | Restrict file/command access to workspace |
| `provider` | string | `""` | Explicit provider name (optional) |
| `model` | string | `glm-4.7` | Primary model to use |
| `model_fallbacks` | []string | `[]` | Fallback models if primary fails |
| `image_model` | string | `""` | Model for image tasks |
| `image_model_fallbacks` | []string | `[]` | Image model fallbacks |
| `max_tokens` | int | `8192` | Maximum tokens in response |
| `temperature` | float | `0.7` | Response randomness (0-1) |
| `max_tool_iterations` | int | `20` | Max tool call iterations |
**Example:**
```json
{
"agents": {
"defaults": {
"workspace": "~/.picoclaw/workspace",
"restrict_to_workspace": true,
"model": "anthropic/claude-opus-4-5",
"model_fallbacks": ["anthropic/claude-sonnet-4", "gpt-4o"],
"max_tokens": 8192,
"temperature": 0.7,
"max_tool_iterations": 20
}
}
}
```
### agents.list (Multi-Agent)
Define multiple agents with different configurations.
| Option | Type | Description |
|--------|------|-------------|
| `id` | string | Unique agent identifier |
| `default` | bool | Is this the default agent |
| `name` | string | Display name |
| `workspace` | string | Agent-specific workspace |
| `model` | object/string | Model config with primary and fallbacks |
| `skills` | []string | Filter available skills |
| `subagents` | object | Subagent configuration |
**Example:**
```json
{
"agents": {
"defaults": { ... },
"list": [
{
"id": "assistant",
"default": true,
"name": "General Assistant",
"workspace": "~/.picoclaw/workspace/assistant",
"model": {
"primary": "anthropic/claude-opus-4-5",
"fallbacks": ["gpt-4o"]
},
"subagents": {
"allow_agents": ["researcher", "coder"]
}
},
{
"id": "researcher",
"name": "Research Agent",
"model": "perplexity/llama-3.1-sonar-large-128k-online",
"skills": ["web-search"]
}
]
}
}
```
## Bindings Configuration
Route messages from channels to specific agents.
| Option | Type | Description |
|--------|------|-------------|
| `agent_id` | string | Target agent ID |
| `match.channel` | string | Channel name |
| `match.account_id` | string | Account filter |
| `match.peer.kind` | string | Peer type (user, group, channel) |
| `match.peer.id` | string | Peer ID |
| `match.guild_id` | string | Discord guild ID |
| `match.team_id` | string | Slack team ID |
**Example:**
```json
{
"bindings": [
{
"agent_id": "personal",
"match": { "channel": "telegram", "peer": { "kind": "user", "id": "123456789" } }
},
{
"agent_id": "work",
"match": { "channel": "slack", "team_id": "T12345" }
}
]
}
```
## Session Configuration
Configure session management.
| Option | Type | Description |
|--------|------|-------------|
| `dm_scope` | string | DM session scope: `main`, `per-agent`, `per-channel` |
| `identity_links` | object | Map user IDs across platforms |
**Example:**
```json
{
"session": {
"dm_scope": "per-agent",
"identity_links": {
"telegram:123456789": ["discord:987654321", "slack:U12345"]
}
}
}
```
## Channels Configuration
Configure chat platform integrations.
### Telegram
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `enabled` | bool | `false` | Enable Telegram channel |
| `token` | string | `""` | Bot token from @BotFather |
| `proxy` | string | `""` | Proxy URL (optional) |
| `allow_from` | []string | `[]` | Allowed user IDs (empty = all) |
```json
{
"channels": {
"telegram": {
"enabled": true,
"token": "123456:ABC...",
"allow_from": ["123456789"]
}
}
}
```
### Discord
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `enabled` | bool | `false` | Enable Discord channel |
| `token` | string | `""` | Bot token |
| `allow_from` | []string | `[]` | Allowed user IDs |
```json
{
"channels": {
"discord": {
"enabled": true,
"token": "MTk4NjIyNDgzNDc...",
"allow_from": ["123456789012345678"]
}
}
}
```
### Slack
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `enabled` | bool | `false` | Enable Slack channel |
| `bot_token` | string | `""` | Bot token (xoxb-...) |
| `app_token` | string | `""` | App token (xapp-...) |
| `allow_from` | []string | `[]` | Allowed user IDs |
### LINE
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `enabled` | bool | `false` | Enable LINE channel |
| `channel_secret` | string | `""` | Channel secret |
| `channel_access_token` | string | `""` | Channel access token |
| `webhook_host` | string | `0.0.0.0` | Webhook host |
| `webhook_port` | int | `18791` | Webhook port |
| `webhook_path` | string | `/webhook/line` | Webhook path |
| `allow_from` | []string | `[]` | Allowed user IDs |
### WhatsApp
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `enabled` | bool | `false` | Enable WhatsApp channel |
| `bridge_url` | string | `ws://localhost:3001` | Bridge WebSocket URL |
| `allow_from` | []string | `[]` | Allowed user IDs |
### Feishu/Lark
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `enabled` | bool | `false` | Enable Feishu channel |
| `app_id` | string | `""` | App ID |
| `app_secret` | string | `""` | App secret |
| `encrypt_key` | string | `""` | Encryption key |
| `verification_token` | string | `""` | Verification token |
| `allow_from` | []string | `[]` | Allowed user IDs |
### DingTalk
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `enabled` | bool | `false` | Enable DingTalk channel |
| `client_id` | string | `""` | Client ID |
| `client_secret` | string | `""` | Client secret |
| `allow_from` | []string | `[]` | Allowed user IDs |
### QQ
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `enabled` | bool | `false` | Enable QQ channel |
| `app_id` | string | `""` | App ID |
| `app_secret` | string | `""` | App secret |
| `allow_from` | []string | `[]` | Allowed user IDs |
### OneBot
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `enabled` | bool | `false` | Enable OneBot channel |
| `ws_url` | string | `ws://127.0.0.1:3001` | WebSocket URL |
| `access_token` | string | `""` | Access token |
| `reconnect_interval` | int | `5` | Reconnect interval (seconds) |
| `group_trigger_prefix` | []string | `[]` | Trigger prefixes for groups |
| `allow_from` | []string | `[]` | Allowed user IDs |
### MaixCam
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `enabled` | bool | `false` | Enable MaixCam channel |
| `host` | string | `0.0.0.0` | Server host |
| `port` | int | `18790` | Server port |
| `allow_from` | []string | `[]` | Allowed user IDs |
## Providers Configuration
Configure LLM providers. See [Providers Guide](../user-guide/providers/README.md) for detailed setup.
### Common Provider Options
| Option | Type | Description |
|--------|------|-------------|
| `api_key` | string | API key |
| `api_base` | string | API base URL (optional) |
| `proxy` | string | Proxy URL (optional) |
| `auth_method` | string | Auth method: `oauth`, `token`, `codex-cli` |
### Provider-Specific Options
**OpenAI:**
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `web_search` | bool | `true` | Enable web search in responses |
**Example:**
```json
{
"providers": {
"openrouter": {
"api_key": "sk-or-v1-xxx",
"api_base": "https://openrouter.ai/api/v1"
},
"zhipu": {
"api_key": "xxx.xxx",
"api_base": "https://open.bigmodel.cn/api/paas/v4"
},
"anthropic": {
"api_key": "",
"auth_method": "token"
},
"openai": {
"api_key": "",
"web_search": true,
"auth_method": "oauth"
},
"groq": {
"api_key": "gsk_xxx"
},
"gemini": {
"api_key": ""
},
"ollama": {
"api_key": "",
"api_base": "http://localhost:11434/v1"
},
"vllm": {
"api_key": "local",
"api_base": "http://localhost:8000/v1"
}
}
}
```
## Tools Configuration
Configure tool behavior.
### Web Tools
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `brave.enabled` | bool | `false` | Enable Brave Search |
| `brave.api_key` | string | `""` | Brave API key |
| `brave.max_results` | int | `5` | Max search results |
| `duckduckgo.enabled` | bool | `true` | Enable DuckDuckGo |
| `duckduckgo.max_results` | int | `5` | Max search results |
| `perplexity.enabled` | bool | `false` | Enable Perplexity |
| `perplexity.api_key` | string | `""` | Perplexity API key |
| `perplexity.max_results` | int | `5` | Max search results |
### Cron Tools
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `exec_timeout_minutes` | int | `5` | Timeout for cron jobs (0 = no timeout) |
### Exec Tools
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `enable_deny_patterns` | bool | `true` | Enable dangerous command blocking |
| `custom_deny_patterns` | []string | `[]` | Additional patterns to block |
**Example:**
```json
{
"tools": {
"web": {
"brave": {
"enabled": true,
"api_key": "BSA...",
"max_results": 5
},
"duckduckgo": {
"enabled": true,
"max_results": 5
}
},
"cron": {
"exec_timeout_minutes": 5
},
"exec": {
"enable_deny_patterns": true,
"custom_deny_patterns": ["wget.*"]
}
}
}
```
## Gateway Configuration
Configure the gateway server.
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `host` | string | `0.0.0.0` | Server host |
| `port` | int | `18790` | Server port |
```json
{
"gateway": {
"host": "0.0.0.0",
"port": 18790
}
}
```
## Heartbeat Configuration
Configure periodic tasks.
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `enabled` | bool | `true` | Enable heartbeat service |
| `interval` | int | `30` | Check interval in minutes (min: 5) |
```json
{
"heartbeat": {
"enabled": true,
"interval": 30
}
}
```
## Devices Configuration
Configure device monitoring.
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `enabled` | bool | `false` | Enable device service |
| `monitor_usb` | bool | `true` | Monitor USB devices (Linux only) |
```json
{
"devices": {
"enabled": false,
"monitor_usb": true
}
}
```
## Environment Variables
All configuration options can be overridden with environment variables using the pattern:
```
PICOCLAW_<SECTION>_<KEY>
```
### Examples
| Config Path | Environment Variable |
|-------------|---------------------|
| `agents.defaults.model` | `PICOCLAW_AGENTS_DEFAULTS_MODEL` |
| `providers.openrouter.api_key` | `PICOCLAW_PROVIDERS_OPENROUTER_API_KEY` |
| `channels.telegram.enabled` | `PICOCLAW_CHANNELS_TELEGRAM_ENABLED` |
| `tools.web.duckduckgo.enabled` | `PICOCLAW_TOOLS_WEB_DUCKDUCKGO_ENABLED` |
| `heartbeat.enabled` | `PICOCLAW_HEARTBEAT_ENABLED` |
| `heartbeat.interval` | `PICOCLAW_HEARTBEAT_INTERVAL` |
**Usage:**
```bash
export PICOCLAW_AGENTS_DEFAULTS_MODEL="gpt-4o"
export PICOCLAW_PROVIDERS_OPENROUTER_API_KEY="sk-or-v1-xxx"
export PICOCLAW_HEARTBEAT_ENABLED="false"
picoclaw agent -m "Hello"
```
## Complete Example
```json
{
"agents": {
"defaults": {
"workspace": "~/.picoclaw/workspace",
"restrict_to_workspace": true,
"model": "anthropic/claude-opus-4-5",
"model_fallbacks": ["gpt-4o", "glm-4.7"],
"max_tokens": 8192,
"temperature": 0.7,
"max_tool_iterations": 20
}
},
"channels": {
"telegram": {
"enabled": true,
"token": "123456:ABC...",
"allow_from": ["123456789"]
},
"discord": {
"enabled": true,
"token": "MTk4NjIyNDgzNDc...",
"allow_from": ["123456789012345678"]
}
},
"providers": {
"openrouter": {
"api_key": "sk-or-v1-xxx"
},
"groq": {
"api_key": "gsk_xxx"
},
"zhipu": {
"api_key": "xxx.xxx"
}
},
"tools": {
"web": {
"brave": {
"enabled": true,
"api_key": "BSA...",
"max_results": 5
},
"duckduckgo": {
"enabled": true,
"max_results": 5
}
}
},
"gateway": {
"host": "0.0.0.0",
"port": 18790
},
"heartbeat": {
"enabled": true,
"interval": 30
}
}
```

176
docs/deployment/README.md Normal file
View file

@ -0,0 +1,176 @@
# Deployment Guide
This section covers deploying PicoClaw in various environments, from local development to production servers and embedded devices.
## Deployment Options
PicoClaw is designed to run anywhere - from powerful servers to ultra-low-cost single-board computers. Choose the deployment method that fits your needs:
### By Environment
| Environment | Best For | Guide |
|-------------|----------|-------|
| **Docker** | Containerized deployments, easy scaling | [Docker Guide](docker.md) |
| **Systemd** | Linux servers, always-on services | [Systemd Guide](systemd.md) |
| **Termux** | Android phones/tablets | [Termux Guide](termux.md) |
| **Single-Board Computers** | Edge devices, IoT | [SBC Guide](sbc/README.md) |
### By Hardware
| Hardware | Cost | Use Case |
|----------|------|----------|
| Any Linux server | Varies | Production deployments |
| Raspberry Pi 4/5 | $35-80 | Home automation, bots |
| LicheeRV Nano | $9.9 | Ultra-low-cost edge AI |
| MaixCAM | $50 | AI camera applications |
| Android (Termux) | Free | Repurpose old phones |
## Quick Start
### Option 1: Binary (Simplest)
```bash
# Download precompiled binary
wget https://github.com/sipeed/picoclaw/releases/latest/download/picoclaw-linux-amd64
chmod +x picoclaw-linux-amd64
# Initialize configuration
./picoclaw-linux-amd64 onboard
# Edit config with your API keys
nano ~/.picoclaw/config.json
# Run gateway (always-on bot)
./picoclaw-linux-amd64 gateway
```
### Option 2: Docker
```bash
# Clone repository
git clone https://github.com/sipeed/picoclaw.git
cd picoclaw
# Configure
cp config/config.example.json config/config.json
# Edit config.json with your API keys
# Start gateway
docker compose --profile gateway up -d
```
### Option 3: Build from Source
```bash
# Requires Go 1.21+
git clone https://github.com/sipeed/picoclaw.git
cd picoclaw
make deps
make build
make install
picoclaw onboard
picoclaw gateway
```
## Operating Modes
PicoClaw supports two main operating modes:
### Agent Mode (One-Shot)
Run a single query and exit. Useful for CLI integration, scripts, and testing.
```bash
# Single query
picoclaw agent -m "What is the weather today?"
# Interactive session
picoclaw agent
# Debug mode
picoclaw agent --debug -m "Hello"
```
### Gateway Mode (Always-On)
Run as a long-running bot that connects to chat platforms.
```bash
# Start gateway (connects to Telegram, Discord, etc.)
picoclaw gateway
# With debug logging
picoclaw gateway --debug
```
## Configuration
PicoClaw uses a single configuration file at `~/.picoclaw/config.json`. See the [Configuration File Reference](../configuration/config-file.md) for complete details.
### Minimum Configuration
```json
{
"agents": {
"defaults": {
"model": "openrouter/anthropic/claude-opus-4-5"
}
},
"providers": {
"openrouter": {
"api_key": "sk-or-v1-your-key-here"
}
}
}
```
### Environment Variables
All config options can be set via environment variables:
```bash
export PICOCLAW_AGENTS_DEFAULTS_MODEL="gpt-4o"
export PICOCLAW_PROVIDERS_OPENROUTER_API_KEY="sk-or-v1-xxx"
picoclaw agent -m "Hello"
```
## Next Steps
1. **Docker Deployment** - [docker.md](docker.md) - Container-based deployment
2. **Systemd Service** - [systemd.md](systemd.md) - Run as a Linux service
3. **Security Checklist** - [security.md](security.md) - Production security
4. **Single-Board Computers** - [sbc/README.md](sbc/README.md) - Raspberry Pi, LicheeRV, MaixCAM
5. **Android/Termux** - [termux.md](termux.md) - Run on Android devices
## Troubleshooting
### Common Issues
**Permission denied:**
```bash
chmod +x picoclaw-*
```
**Command not found:**
```bash
# Add to PATH
export PATH="$PWD:$PATH"
# Or install to system
sudo mv picoclaw-* /usr/local/bin/picoclaw
```
**Config file not found:**
```bash
# Initialize config
picoclaw onboard
```
**API errors:**
- Verify API keys are correct
- Check network connectivity
- Review provider-specific documentation
For more help, see the [Troubleshooting Guide](../operations/troubleshooting.md).

433
docs/deployment/docker.md Normal file
View file

@ -0,0 +1,433 @@
# Docker Deployment
PicoClaw provides official Docker support with multi-stage builds for minimal image sizes. This guide covers deploying PicoClaw using Docker and Docker Compose.
## Prerequisites
- Docker 20.10 or later
- Docker Compose V2 (recommended)
- API keys for your LLM providers
## Quick Start
### Using Docker Compose (Recommended)
```bash
# Clone the repository
git clone https://github.com/sipeed/picoclaw.git
cd picoclaw
# Create configuration
mkdir -p config
cp config/config.example.json config/config.json
# Edit configuration with your API keys
nano config/config.json
# Start gateway mode (always-on bot)
docker compose --profile gateway up -d
# View logs
docker compose logs -f picoclaw-gateway
```
### One-Shot Agent Mode
Run a single query using Docker:
```bash
# Run a one-shot query
docker compose run --rm picoclaw-agent -m "Hello, how are you?"
# Interactive mode
docker compose run --rm -it picoclaw-agent
```
## Docker Compose Configuration
The included `docker-compose.yml` defines two services:
### Gateway Service (Always-On Bot)
```yaml
picoclaw-gateway:
build:
context: .
dockerfile: Dockerfile
container_name: picoclaw-gateway
restart: unless-stopped
profiles:
- gateway
volumes:
- ./config/config.json:/home/picoclaw/.picoclaw/config.json:ro
- picoclaw-workspace:/home/picoclaw/.picoclaw/workspace
command: ["gateway"]
```
### Agent Service (One-Shot)
```yaml
picoclaw-agent:
build:
context: .
dockerfile: Dockerfile
container_name: picoclaw-agent
profiles:
- agent
volumes:
- ./config/config.json:/home/picoclaw/.picoclaw/config.json:ro
- picoclaw-workspace:/home/picoclaw/.picoclaw/workspace
entrypoint: ["picoclaw", "agent"]
stdin_open: true
tty: true
```
## Building the Image
### Standard Build
```bash
# Build using Docker Compose
docker compose build
# Or build directly
docker build -t picoclaw:latest .
```
### Build with Custom Arguments
```bash
# Build with specific Go version
docker build --build-arg GO_VERSION=1.23 -t picoclaw:latest .
```
### Multi-Platform Build
Build for multiple architectures using buildx:
```bash
# Enable buildx
docker buildx create --use
# Build for multiple platforms
docker buildx build --platform linux/amd64,linux/arm64 -t picoclaw:latest .
```
## Running the Container
### Basic Run
```bash
# Run gateway mode
docker run -d \
--name picoclaw \
-v $(pwd)/config/config.json:/home/picoclaw/.picoclaw/config.json:ro \
-v picoclaw-workspace:/home/picoclaw/.picoclaw/workspace \
picoclaw:latest gateway
# Run agent mode (one-shot)
docker run --rm \
-v $(pwd)/config/config.json:/home/picoclaw/.picoclaw/config.json:ro \
-v picoclaw-workspace:/home/picoclaw/.picoclaw/workspace \
picoclaw:latest agent -m "Hello"
```
### With Environment Variables
```bash
docker run -d \
--name picoclaw \
-e PICOCLAW_AGENTS_DEFAULTS_MODEL="gpt-4o" \
-e PICOCLAW_PROVIDERS_OPENROUTER_API_KEY="sk-or-v1-xxx" \
-v picoclaw-workspace:/home/picoclaw/.picoclaw/workspace \
picoclaw:latest gateway
```
### With Port Mapping
If you need to expose the gateway HTTP server:
```bash
docker run -d \
--name picoclaw \
-p 18790:18790 \
-v $(pwd)/config/config.json:/home/picoclaw/.picoclaw/config.json:ro \
-v picoclaw-workspace:/home/picoclaw/.picoclaw/workspace \
picoclaw:latest gateway
```
## Volume Management
### Persistent Workspace
The workspace volume stores sessions, memory, and other persistent data:
```bash
# List volumes
docker volume ls
# Inspect workspace volume
docker volume inspect picoclaw-workspace
# Backup workspace
docker run --rm -v picoclaw-workspace:/data -v $(pwd):/backup alpine tar czf /backup/workspace-backup.tar.gz /data
# Restore workspace
docker run --rm -v picoclaw-workspace:/data -v $(pwd):/backup alpine tar xzf /backup/workspace-backup.tar.gz -C /
```
### Configuration Mount
Configuration is mounted read-only for security:
```bash
# Mount config from host
-v /path/to/config.json:/home/picoclaw/.picoclaw/config.json:ro
```
## Health Checks
The Dockerfile includes a built-in health check:
```dockerfile
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD wget -q --spider http://localhost:18790/health || exit 1
```
Check container health:
```bash
# View health status
docker ps --format "table {{.Names}}\t{{.Status}}"
# Inspect health details
docker inspect --format='{{json .State.Health}}' picoclaw-gateway | jq
```
## Logging
### View Logs
```bash
# Docker Compose logs
docker compose logs -f picoclaw-gateway
# Docker logs
docker logs -f picoclaw-gateway
# Last 100 lines
docker logs --tail 100 picoclaw-gateway
```
### Configure Log Driver
```yaml
services:
picoclaw-gateway:
# ... other config ...
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
```
## Advanced Configuration
### Custom Docker Compose File
Create `docker-compose.prod.yml` for production:
```yaml
services:
picoclaw-gateway:
image: picoclaw:latest
restart: always
environment:
- PICOCLAW_HEARTBEAT_ENABLED=true
- PICOCLAW_HEARTBEAT_INTERVAL=30
volumes:
- ./config/production.json:/home/picoclaw/.picoclaw/config.json:ro
- picoclaw-workspace:/home/picoclaw/.picoclaw/workspace
logging:
driver: "json-file"
options:
max-size: "50m"
max-file: "5"
deploy:
resources:
limits:
memory: 512M
reservations:
memory: 128M
command: ["gateway"]
volumes:
picoclaw-workspace:
```
Run with:
```bash
docker compose -f docker-compose.prod.yml up -d
```
### Network Configuration
For connecting to other services:
```yaml
services:
picoclaw-gateway:
networks:
- picoclaw-net
- external-net
networks:
picoclaw-net:
driver: bridge
external-net:
external: true
```
### Secrets Management
Using Docker secrets (Swarm mode):
```yaml
services:
picoclaw-gateway:
secrets:
- openrouter_api_key
environment:
- PICOCLAW_PROVIDERS_OPENROUTER_API_KEY_FILE=/run/secrets/openrouter_api_key
secrets:
openrouter_api_key:
external: true
```
## Production Deployment
### Recommendations
1. **Use specific version tags** instead of `latest`:
```bash
docker pull picoclaw:v0.1.1
```
2. **Set resource limits**:
```yaml
deploy:
resources:
limits:
memory: 512M
cpus: '1.0'
```
3. **Configure log rotation** to prevent disk exhaustion
4. **Use health checks** for orchestration
5. **Mount configuration read-only** for security
### Example Production docker-compose.yml
```yaml
version: "3.8"
services:
picoclaw-gateway:
image: ghcr.io/sipeed/picoclaw:v0.1.1
container_name: picoclaw-gateway
restart: always
profiles:
- gateway
volumes:
- ./config/production.json:/home/picoclaw/.picoclaw/config.json:ro
- picoclaw-workspace:/home/picoclaw/.picoclaw/workspace
environment:
- TZ=UTC
logging:
driver: "json-file"
options:
max-size: "50m"
max-file: "5"
deploy:
resources:
limits:
memory: 512M
reservations:
memory: 128M
healthcheck:
test: ["CMD", "wget", "-q", "--spider", "http://localhost:18790/health"]
interval: 30s
timeout: 3s
retries: 3
start_period: 10s
command: ["gateway"]
volumes:
picoclaw-workspace:
driver: local
```
## Troubleshooting
### Container won't start
```bash
# Check logs
docker compose logs picoclaw-gateway
# Check config file exists
ls -la config/config.json
# Verify JSON syntax
cat config/config.json | jq .
```
### Permission issues
```bash
# The container runs as non-root user (uid 1000)
# Ensure config file is readable
chmod 644 config/config.json
```
### API connection issues
```bash
# Verify network connectivity from container
docker compose exec picoclaw-gateway wget -q -O- https://api.openai.com/v1/models
# Check DNS resolution
docker compose exec picoclaw-gateway nslookup api.openai.com
```
### Volume issues
```bash
# List volumes
docker volume ls
# Remove and recreate volume (WARNING: destroys data)
docker compose down -v
docker compose up -d
```
### Reset everything
```bash
# Stop containers
docker compose down
# Remove volumes
docker compose down -v
# Rebuild image
docker compose build --no-cache
# Start fresh
docker compose --profile gateway up -d
```

View file

@ -0,0 +1,351 @@
# Single-Board Computer Deployment
PicoClaw is optimized for resource-constrained environments, making it ideal for single-board computers (SBCs). This section covers deployment on popular low-cost hardware platforms.
## Why PicoClaw on SBCs?
- **Ultra-lightweight**: Single binary, minimal dependencies
- **Low resource usage**: Runs comfortably on 256MB RAM
- **Native ARM64 support**: No emulation required
- **Offline capable**: Works with local LLM providers (Ollama, vLLM)
- **Always-on**: Low power consumption for 24/7 operation
## Supported Hardware
| Hardware | Price | Architecture | RAM | Recommended For |
|----------|-------|--------------|-----|-----------------|
| [Raspberry Pi 4/5](rpi.md) | $35-80 | ARM64 | 2-8GB | Home automation, general use |
| [LicheeRV Nano](licheerv-nano.md) | $9.9 | RISC-V | 64MB | Ultra-low-cost edge AI |
| [MaixCAM](maixcam.md) | $50 | RISC-V | 256MB | AI camera applications |
| Orange Pi | $15-50 | ARM64 | 1-4GB | Budget alternative |
| Rock Pi | $35-75 | ARM64 | 1-4GB | More I/O options |
| NanoPi | $15-60 | ARM64 | 512MB-4GB | Compact form factor |
## Architecture Support
PicoClaw provides precompiled binaries for all major SBC architectures:
| Architecture | Binary Name | Devices |
|--------------|-------------|---------|
| ARM64 | `picoclaw-linux-arm64` | Raspberry Pi 4/5, Orange Pi, most SBCs |
| RISC-V 64 | `picoclaw-linux-riscv64` | LicheeRV Nano, MaixCAM |
| LoongArch | `picoclaw-linux-loong64` | Loongson-based devices |
## Quick Start
### Generic Installation
Most SBCs running Linux can use this approach:
```bash
# Download the appropriate binary for your architecture
# For ARM64 (most SBCs):
wget https://github.com/sipeed/picoclaw/releases/latest/download/picoclaw-linux-arm64
# For RISC-V:
wget https://github.com/sipeed/picoclaw/releases/latest/download/picoclaw-linux-riscv64
# Make executable
chmod +x picoclaw-linux-*
# Initialize
./picoclaw-linux-* onboard
# Configure
nano ~/.picoclaw/config.json
# Run
./picoclaw-linux-* gateway
```
### Check Your Architecture
```bash
uname -m
# aarch64 = ARM64 (use picoclaw-linux-arm64)
# riscv64 = RISC-V (use picoclaw-linux-riscv64)
# loongarch64 = LoongArch (use picoclaw-linux-loong64)
```
## Common Configuration
### Minimal Memory Configuration
For devices with limited RAM:
```json
{
"agents": {
"defaults": {
"model": "openrouter/anthropic/claude-sonnet-4",
"max_tokens": 2048,
"max_tool_iterations": 10
}
},
"heartbeat": {
"enabled": false
},
"devices": {
"enabled": false
}
}
```
### Local LLM Integration
Use with Ollama for offline operation:
```json
{
"agents": {
"defaults": {
"model": "ollama/llama3.2:1b"
}
},
"providers": {
"ollama": {
"api_base": "http://localhost:11434/v1"
}
}
}
```
### Power Management
For battery-powered or solar setups:
```bash
# Reduce CPU frequency
echo powersave | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
# Disable unnecessary services
sudo systemctl disable bluetooth
sudo systemctl disable avahi-daemon
```
## Performance Tuning
### Memory Optimization
```bash
# Create swap file (if needed)
sudo fallocate -l 1G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
# Add to /etc/fstab for persistence
/swapfile none swap sw 0 0
```
### CPU Optimization
```bash
# Check CPU info
cat /proc/cpuinfo
# Set performance governor
echo performance | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
```
### Storage Optimization
```bash
# Use tmpfs for temporary files
sudo mount -t tmpfs -o size=100M tmpfs /tmp
# Disable access time updates in /etc/fstab
# Add noatime to your root partition options
```
## Systemd Service Setup
For always-on operation, set up as a systemd service:
```bash
# Create service file
sudo tee /etc/systemd/system/picoclaw.service << 'EOF'
[Unit]
Description=PicoClaw AI Assistant
After=network.target
[Service]
Type=simple
User=picoclaw
ExecStart=/usr/local/bin/picoclaw gateway
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
# Enable and start
sudo systemctl daemon-reload
sudo systemctl enable picoclaw
sudo systemctl start picoclaw
```
See the [Systemd Guide](../systemd.md) for detailed configuration.
## Network Configuration
### Static IP
Set up a static IP for reliable access:
```bash
# Using nmcli
nmcli con mod "Wired connection 1" ipv4.addresses 192.168.1.100/24
nmcli con mod "Wired connection 1" ipv4.gateway 192.168.1.1
nmcli con mod "Wired connection 1" ipv4.dns "8.8.8.8"
nmcli con mod "Wired connection 1" ipv4.method manual
nmcli con up "Wired connection 1"
```
### WiFi Setup
```bash
# Using nmcli
nmcli dev wifi connect "SSID" password "PASSWORD"
```
### Access Point Mode
Turn your SBC into a WiFi access point:
```bash
# Install hostapd
sudo apt install hostapd dnsmasq
# Configure access point
sudo tee /etc/hostapd/hostapd.conf << 'EOF'
interface=wlan0
driver=nl80211
ssid=PicoClaw
hw_mode=g
channel=7
wpa=2
wpa_passphrase=yourpassword
wpa_key_mgmt=WPA-PSK
EOF
# Enable
sudo systemctl enable hostapd
sudo systemctl start hostapd
```
## Monitoring
### Resource Monitoring
```bash
# Install monitoring tools
sudo apt install htop iotop
# Monitor resources
htop
# Check temperature (Raspberry Pi)
vcgencmd measure_temp
# Check memory
free -h
```
### Health Monitoring Script
```bash
#!/bin/bash
# health-check.sh
# Check if PicoClaw is running
if ! pgrep -f "picoclaw gateway" > /dev/null; then
echo "PicoClaw not running, restarting..."
systemctl restart picoclaw
fi
# Check memory usage
MEM_USED=$(free | grep Mem | awk '{print int($3/$2 * 100)}')
if [ "$MEM_USED" -gt 90 ]; then
echo "Memory usage high: ${MEM_USED}%"
fi
# Check disk space
DISK_USED=$(df -h / | tail -1 | awk '{print int($5)}')
if [ "$DISK_USED" -gt 90 ]; then
echo "Disk usage high: ${DISK_USED}%"
fi
```
## Troubleshooting
### Out of Memory
```bash
# Check memory
free -h
# Add swap
sudo fallocate -l 512M /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
# Reduce memory in config
# Set lower max_tokens value
```
### Slow Performance
```bash
# Check CPU governor
cat /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
# Set performance mode
echo performance | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
# Check for thermal throttling
cat /sys/class/thermal/thermal_zone*/temp
```
### Network Issues
```bash
# Check network interface
ip addr
# Test connectivity
ping google.com
# Check DNS
nslookup api.openai.com
```
### Binary Not Executing
```bash
# Check architecture
uname -m
# Verify binary architecture
file picoclaw-linux-*
# Check permissions
ls -la picoclaw-linux-*
# Check for missing libraries
ldd picoclaw-linux-*
```
## Hardware-Specific Guides
- [Raspberry Pi 4/5](rpi.md) - Full guide for the most popular SBC
- [LicheeRV Nano](licheerv-nano.md) - Ultra-low-cost RISC-V board
- [MaixCAM](maixcam.md) - AI camera with built-in PicoClaw support
## Community Resources
- [PicoClaw GitHub](https://github.com/sipeed/picoclaw)
- [Sipeed Wiki](https://wiki.sipeed.com/)
- [Raspberry Pi Forums](https://forums.raspberrypi.com/)

View file

@ -0,0 +1,479 @@
# LicheeRV Nano Deployment
LicheeRV Nano is an ultra-low-cost RISC-V single-board computer at just $9.9, making it the most affordable way to run PicoClaw. This guide covers setup and deployment on this remarkable little board.
## Hardware Specifications
| Specification | Value |
|---------------|-------|
| CPU | SG2002 (RISC-V C906 @ 1GHz) |
| RAM | 64MB DDR2 |
| Storage | MicroSD card slot |
| Network | 10/100 Ethernet |
| USB | 1x USB 2.0 |
| Video | HDMI output |
| Price | $9.9 USD |
## Where to Buy
- [Sipeed Official Store](https://www.aliexpress.com/store/911197660)
- [Seeed Studio](https://www.seeedstudio.com/)
## Operating System Setup
### Download Image
LicheeRV Nano uses Buildroot-based Linux images:
```bash
# Download from Sipeed
# https://github.com/sipeed/LicheeRV-Nano-Build/releases
# Choose the latest release
wget https://github.com/sipeed/LicheeRV-Nano-Build/releases/download/v0.2/licheervnano-0.2.img.gz
# Decompress
gunzip licheervnano-0.2.img.gz
```
### Flash to SD Card
```bash
# Using dd (Linux/macOS)
sudo dd if=licheervnano-0.2.img of=/dev/sdX bs=4M status=progress
sync
# Or use balenaEtcher (cross-platform)
# https://www.balena.io/etcher/
```
### First Boot
1. Insert the microSD card into LicheeRV Nano
2. Connect HDMI monitor (optional) or serial console
3. Connect Ethernet
4. Power on via USB-C
Default login:
- Username: `root`
- Password: `licheepi` (or no password)
### Serial Console Setup
If you don't have HDMI:
```bash
# Connect USB-TTL adapter to GPIO pins:
# - TX -> GPIO 12 (RX)
# - RX -> GPIO 13 (TX)
# - GND -> GND
# Use screen or minicom
screen /dev/ttyUSB0 115200
# or
minicom -D /dev/ttyUSB0
```
## Network Configuration
### DHCP (Default)
The system should automatically obtain an IP address via DHCP:
```bash
# Check IP address
ip addr show eth0
# Or check DHCP leases on your router
```
### Static IP
```bash
# Edit network configuration
cat > /etc/network/interfaces.d/eth0 << 'EOF'
auto eth0
iface eth0 inet static
address 192.168.1.100
netmask 255.255.255.0
gateway 192.168.1.1
dns-nameservers 8.8.8.8 8.8.4.4
EOF
# Restart networking
/etc/init.d/networking restart
```
### SSH Access
```bash
# Start SSH daemon (if not running)
/etc/init.d/ssh start
# Enable on boot
update-rc.d ssh defaults
# Connect from another machine
ssh root@192.168.1.100
```
## Installing PicoClaw
### Download RISC-V Binary
```bash
# Download RISC-V 64-bit binary
wget https://github.com/sipeed/picoclaw/releases/latest/download/picoclaw-linux-riscv64
# Make executable
chmod +x picoclaw-linux-riscv64
# Move to system path
mv picoclaw-linux-riscv64 /usr/local/bin/picoclaw
```
### Initialize Configuration
```bash
# Initialize
picoclaw onboard
# Edit configuration
vi ~/.picoclaw/config.json
```
### Minimal Configuration
Due to limited memory (64MB), use minimal settings:
```json
{
"agents": {
"defaults": {
"workspace": "~/.picoclaw/workspace",
"restrict_to_workspace": true,
"model": "openrouter/anthropic/claude-sonnet-4",
"max_tokens": 1024,
"max_tool_iterations": 5,
"temperature": 0.7
}
},
"providers": {
"openrouter": {
"api_key": "sk-or-v1-your-key-here"
}
},
"gateway": {
"host": "127.0.0.1",
"port": 18790
},
"heartbeat": {
"enabled": false
},
"devices": {
"enabled": false
}
}
```
## Memory Optimization
The 64MB RAM limitation requires careful optimization:
### Create Swap File
```bash
# Create 128MB swap file
dd if=/dev/zero of=/swapfile bs=1M count=128
mkswap /swapfile
swapon /swapfile
# Add to fstab for persistence
echo "/swapfile none swap sw 0 0" >> /etc/fstab
```
### Disable Unnecessary Services
```bash
# List running services
ps aux
# Stop and disable unnecessary services
/etc/init.d/crond stop
update-rc.d -f crond remove
# If not using GUI
/etc/init.d/lightdm stop
update-rc.d -f lightdm remove
```
### Use tmpfs
```bash
# Mount /tmp as tmpfs
mount -t tmpfs -o size=16M tmpfs /tmp
# Add to fstab
echo "tmpfs /tmp tmpfs defaults,size=16M 0 0" >> /etc/fstab
```
## Running PicoClaw
### Interactive Testing
```bash
# Test agent mode
picoclaw agent -m "Hello"
# Debug mode
picoclaw agent --debug -m "What is 2+2?"
```
### Gateway Mode
```bash
# Start gateway
picoclaw gateway
# In background
nohup picoclaw gateway > picoclaw.log 2>&1 &
# View logs
tail -f picoclaw.log
```
### As a Service
Create init script for Buildroot:
```bash
cat > /etc/init.d/picoclaw << 'EOF'
#!/bin/sh
DAEMON=/usr/local/bin/picoclaw
DAEMON_ARGS="gateway"
PIDFILE=/var/run/picoclaw.pid
case "$1" in
start)
echo "Starting PicoClaw..."
start-stop-daemon -S -b -m -p $PIDFILE -x $DAEMON -- $DAEMON_ARGS
;;
stop)
echo "Stopping PicoClaw..."
start-stop-daemon -K -p $PIDFILE -x $DAEMON
rm -f $PIDFILE
;;
restart)
$0 stop
sleep 1
$0 start
;;
status)
if [ -f $PIDFILE ]; then
echo "PicoClaw is running"
else
echo "PicoClaw is not running"
fi
;;
*)
echo "Usage: $0 {start|stop|restart|status}"
exit 1
;;
esac
exit 0
EOF
chmod +x /etc/init.d/picoclaw
update-rc.d picoclaw defaults
```
## Use Cases
### Telegram Bot
```json
{
"channels": {
"telegram": {
"enabled": true,
"token": "YOUR_BOT_TOKEN",
"allow_from": ["YOUR_USER_ID"]
}
}
}
```
### Home Automation Controller
Use with GPIO for home automation:
```bash
# Control GPIO (example)
echo 17 > /sys/class/gpio/export
echo out > /sys/class/gpio/gpio17/direction
echo 1 > /sys/class/gpio/gpio17/value
```
### Edge AI Integration
Process sensor data and make decisions:
```json
{
"tools": {
"exec": {
"enable_deny_patterns": true,
"custom_deny_patterns": ["rm -rf", "reboot"]
}
},
"heartbeat": {
"enabled": true,
"interval": 60
}
}
```
## Performance Tips
### Optimize Network
```bash
# Use wired Ethernet for stability
# Keep connections minimal
# Reduce DNS lookups
echo "nameserver 8.8.8.8" > /etc/resolv.conf
```
### Reduce Logging
```bash
# Run without debug output
picoclaw gateway
# Limit log file size
picoclaw gateway 2>&1 | rotatelogs /var/log/picoclaw-%Y%m%d.log 86400 &
```
### Monitor Resources
```bash
# Check memory
free -m
# Check CPU
top
# Check temperature (if available)
cat /sys/class/thermal/thermal_zone*/temp
```
## Troubleshooting
### Out of Memory
```bash
# Check memory usage
free -m
# If OOM, increase swap
swapoff /swapfile
dd if=/dev/zero of=/swapfile bs=1M count=256
mkswap /swapfile
swapon /swapfile
# Reduce max_tokens in config
```
### Binary Not Executing
```bash
# Check architecture
uname -m
# Should show: riscv64
# Verify binary
file /usr/local/bin/picoclaw
# Check if executable
ls -la /usr/local/bin/picoclaw
# Check dependencies
ldd /usr/local/bin/picoclaw
```
### Network Issues
```bash
# Check interface
ip addr
# Test connectivity
ping -c 3 google.com
# Test DNS
nslookup api.openai.com
# Check routes
ip route
```
### Service Won't Start
```bash
# Check if already running
ps aux | grep picoclaw
# Check logs
cat picoclaw.log
# Test manually
picoclaw gateway
```
## Advanced Configuration
### Watchdog
Set up hardware watchdog for automatic reboot on failure:
```bash
# Load watchdog module
modprobe dw_wdt
# Configure watchdog
cat > /etc/watchdog.conf << 'EOF'
watchdog-device = /dev/watchdog
interval = 10
retry-timeout = 60
repair-max = 1
EOF
# Start watchdog daemon
watchdog
```
### Auto-Restart Script
```bash
#!/bin/sh
# /usr/local/bin/picoclaw-watchdog.sh
while true; do
if ! pgrep -f "picoclaw gateway" > /dev/null; then
echo "PicoClaw not running, restarting..."
picoclaw gateway >> /var/log/picoclaw.log 2>&1 &
sleep 10
fi
sleep 30
done
```
## Resources
- [LicheeRV Nano Wiki](https://wiki.sipeed.com/hardware/zh/lichee/RV_Nano/1_intro.html)
- [Sipeed GitHub](https://github.com/sipeed)
- [PicoClaw Releases](https://github.com/sipeed/picoclaw/releases)
- [RISC-V International](https://riscv.org/)

View file

@ -0,0 +1,490 @@
# MaixCAM Deployment
MaixCAM is an AI camera platform from Sipeed that comes with PicoClaw pre-integrated. This guide covers deployment and configuration on MaixCAM for AI-powered camera applications.
## Hardware Specifications
| Specification | Value |
|---------------|-------|
| CPU | AX620E (RISC-V C906 @ 1GHz) |
| NPU | 14.4 TOPS (for AI inference) |
| RAM | 256MB DDR3 |
| Storage | MicroSD card slot |
| Camera | GC2145, support for other modules |
| Display | 2.4" 640x480 touchscreen |
| Network | WiFi 6, Ethernet (via dock) |
| USB | 1x USB 2.0 Type-C |
| Price | ~$50 USD |
## Where to Buy
- [Sipeed Official Store](https://www.aliexpress.com/store/911197660)
- [Seeed Studio](https://www.seeedstudio.com/)
- [MaixCAM Product Page](https://wiki.sipeed.com/maixcam)
## Pre-installed PicoClaw
MaixCAM comes with PicoClaw pre-installed and configured. The built-in MaixCAM channel allows direct interaction through the device.
### Quick Start
1. Power on MaixCAM
2. Connect to WiFi (via touchscreen or web interface)
3. PicoClaw starts automatically
4. Interact via the touchscreen or connect external channels
## Initial Setup
### First Boot
```bash
# Default hostname: maixcam.local
# Default credentials: root / root (or no password)
# SSH access
ssh root@maixcam.local
```
### Network Configuration
#### WiFi Setup (Touchscreen)
1. Tap Settings icon on the home screen
2. Select WiFi
3. Choose your network and enter password
#### WiFi Setup (Command Line)
```bash
# Using nmcli
nmcli dev wifi connect "SSID" password "PASSWORD"
# Or using wpa_supplicant
wpa_passphrase "SSID" "PASSWORD" >> /etc/wpa_supplicant.conf
wpa_supplicant -B -i wlan0 -c /etc/wpa_supplicant.conf
udhcpc -i wlan0
```
### Static IP
```bash
# Configure static IP
cat > /etc/network/interfaces.d/eth0 << 'EOF'
auto eth0
iface eth0 inet static
address 192.168.1.100
netmask 255.255.255.0
gateway 192.168.1.1
dns-nameservers 8.8.8.8
EOF
# Restart networking
/etc/init.d/networking restart
```
## PicoClaw Configuration
### Configuration File
```bash
# Edit configuration
vi ~/.picoclaw/config.json
# or
vi /etc/picoclaw/config.json
```
### MaixCAM Channel
The MaixCAM channel provides native integration:
```json
{
"channels": {
"maixcam": {
"enabled": true,
"host": "0.0.0.0",
"port": 18790,
"allow_from": []
}
}
}
```
### Full Configuration Example
```json
{
"agents": {
"defaults": {
"workspace": "~/.picoclaw/workspace",
"restrict_to_workspace": true,
"model": "openrouter/anthropic/claude-sonnet-4",
"max_tokens": 2048,
"temperature": 0.7
}
},
"providers": {
"openrouter": {
"api_key": "sk-or-v1-your-key-here"
},
"zhipu": {
"api_key": "your-zhipu-key"
}
},
"channels": {
"maixcam": {
"enabled": true,
"host": "0.0.0.0",
"port": 18790
},
"telegram": {
"enabled": true,
"token": "YOUR_BOT_TOKEN",
"allow_from": ["YOUR_USER_ID"]
}
},
"tools": {
"web": {
"duckduckgo": {
"enabled": true,
"max_results": 5
}
}
},
"heartbeat": {
"enabled": true,
"interval": 30
}
}
```
## Camera Integration
### Taking Photos
PicoClaw can use the camera through the exec tool:
```bash
# Take a photo
libcamera-still -o /tmp/photo.jpg
# Or using the built-in camera tool
maixcam-capture /tmp/photo.jpg
```
### Camera Skills
Create a skill for camera operations:
```markdown
# Camera Skill
You can use the camera to take photos and analyze them.
## Commands
- Take a photo: `libcamera-still -o /tmp/photo.jpg`
- List photos: `ls -la /tmp/*.jpg`
- Delete photos: `rm /tmp/photo.jpg`
## Example
User: "Take a photo and describe what you see"
Action: Take photo using exec tool, then analyze
```
### Vision Analysis
To use vision capabilities:
1. Set up an image model in config:
```json
{
"agents": {
"defaults": {
"model": "openrouter/anthropic/claude-sonnet-4",
"image_model": "openrouter/anthropic/claude-sonnet-4"
}
}
}
```
2. Take a photo and ask PicoClaw to analyze it
## AI Features
### NPU-Accelerated Inference
MaixCAM has a built-in NPU for AI inference. While PicoClaw uses cloud LLMs by default, you can:
1. Run local vision models on the NPU
2. Use local object detection
3. Process images before sending to cloud
### Local Vision Model
```bash
# Example: Run object detection
# (Specific commands depend on installed packages)
python3 /opt/maixcam/detection.py --input /tmp/photo.jpg
```
### Speech Recognition
MaixCAM supports voice input:
```bash
# Audio recording
arecord -d 5 -f cd /tmp/recording.wav
# Speech-to-text (if configured)
maixcam-asr /tmp/recording.wav
```
## Running PicoClaw
### Starting Manually
```bash
# Start gateway
picoclaw gateway
# With debug output
picoclaw gateway --debug
# Agent mode (one-shot)
picoclaw agent -m "What do you see?"
```
### As a Service
MaixCAM typically runs PicoClaw as a systemd service:
```bash
# Check status
systemctl status picoclaw
# Start/stop/restart
sudo systemctl start picoclaw
sudo systemctl stop picoclaw
sudo systemctl restart picoclaw
# View logs
journalctl -u picoclaw -f
```
### Auto-start on Boot
```bash
# Enable auto-start
sudo systemctl enable picoclaw
# Disable auto-start
sudo systemctl disable picoclaw
```
## Use Cases
### Security Camera
Configure PicoClaw for security monitoring:
```json
{
"heartbeat": {
"enabled": true,
"interval": 5
}
}
```
Create a heartbeat task that:
1. Captures an image
2. Analyzes for anomalies
3. Sends alerts via Telegram
### Smart Doorbell
```json
{
"channels": {
"telegram": {
"enabled": true,
"token": "YOUR_BOT_TOKEN"
},
"maixcam": {
"enabled": true
}
}
}
```
Workflow:
1. Doorbell button triggers camera
2. PicoClaw captures and analyzes image
3. Sends notification with photo to Telegram
### Object Recognition Assistant
Use with the camera for object identification:
```
User: "What is on the table?"
PicoClaw: [Takes photo] "I can see a laptop, coffee mug, and notebook on the table."
```
### Plant Monitor
Monitor plant health:
```json
{
"heartbeat": {
"enabled": true,
"interval": 60
}
}
```
## Performance Optimization
### Memory Management
```bash
# Check memory
free -m
# The 256MB RAM should be sufficient for basic operation
# If needed, reduce max_tokens in config
```
### CPU Frequency
```bash
# Check current frequency
cat /sys/devices/system/cpu/cpu*/cpufreq/scaling_cur_freq
# Set performance governor
echo performance > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
```
### Storage
```bash
# Check disk space
df -h
# Clean up old sessions
rm -rf ~/.picoclaw/workspace/sessions/*.json.old
```
## Web Interface
MaixCAM includes a web interface for configuration:
```
http://maixcam.local/
```
Features:
- Live camera view
- PicoClaw chat interface
- Settings configuration
- System monitoring
## Troubleshooting
### PicoClaw Not Starting
```bash
# Check if running
ps aux | grep picoclaw
# Check logs
journalctl -u picoclaw -n 100
# Test manually
picoclaw gateway --debug
```
### Camera Issues
```bash
# Check camera device
ls -la /dev/video*
# Test camera
libcamera-hello
# Check for errors
dmesg | grep -i camera
```
### WiFi Connection Issues
```bash
# Check WiFi status
nmcli dev status
# Reconnect
nmcli dev wifi connect "SSID" password "PASSWORD"
# Check signal strength
iwconfig wlan0
```
### Touchscreen Not Responding
```bash
# Check input devices
cat /proc/bus/input/devices
# Calibrate touchscreen
ts_calibrate
```
### API Errors
```bash
# Test API connectivity
curl -I https://api.openai.com
# Check DNS
nslookup api.openai.com
# Verify API key
echo $PICOCLAW_PROVIDERS_OPENROUTER_API_KEY
```
## Updates
### Update PicoClaw
```bash
# Download latest version
wget https://github.com/sipeed/picoclaw/releases/latest/download/picoclaw-linux-riscv64
chmod +x picoclaw-linux-riscv64
sudo mv picoclaw-linux-riscv64 /usr/local/bin/picoclaw
# Restart service
sudo systemctl restart picoclaw
```
### System Update
```bash
# Update packages
apt update && apt upgrade -y
# Update firmware (if available)
# Check Sipeed wiki for instructions
```
## Resources
- [MaixCAM Wiki](https://wiki.sipeed.com/maixcam)
- [Sipeed GitHub](https://github.com/sipeed)
- [MaixCAM Examples](https://github.com/sipeed/MaixCAM)
- [PicoClaw GitHub](https://github.com/sipeed/picoclaw)
- [MaixPy Documentation](https://wiki.sipeed.com/maixpy/)

537
docs/deployment/sbc/rpi.md Normal file
View file

@ -0,0 +1,537 @@
# Raspberry Pi Deployment
Raspberry Pi is the most popular single-board computer for running PicoClaw. This guide covers deployment on Raspberry Pi 4 and 5, with notes for older models.
## Prerequisites
- Raspberry Pi 4 or 5 (recommended) or Pi 3B+ (minimum)
- 2GB RAM minimum, 4GB+ recommended
- microSD card (16GB minimum, 32GB+ recommended)
- Raspberry Pi OS (64-bit recommended)
## Operating System Setup
### Download Raspberry Pi OS
```bash
# On your computer, download Raspberry Pi OS Lite (64-bit)
# https://www.raspberrypi.com/software/operating-systems/
# Or use Raspberry Pi Imager
# https://www.raspberrypi.com/software/
```
### Flash and Configure
Using Raspberry Pi Imager (recommended):
1. Insert microSD card
2. Open Raspberry Pi Imager
3. Select "Raspberry Pi OS Lite (64-bit)"
4. Click gear icon for advanced options:
- Set hostname: `picoclaw.local`
- Enable SSH
- Set username/password
- Configure WiFi (if using wireless)
5. Write to card
### First Boot
```bash
# SSH into your Pi
ssh picoclaw@picoclaw.local
# Update system
sudo apt update && sudo apt upgrade -y
# Set timezone
sudo raspi-config
# Navigate to Localisation Options > Timezone
```
## Installing PicoClaw
### Option 1: Precompiled Binary (Recommended)
```bash
# Download ARM64 binary
wget https://github.com/sipeed/picoclaw/releases/latest/download/picoclaw-linux-arm64
# Make executable
chmod +x picoclaw-linux-arm64
# Move to system path
sudo mv picoclaw-linux-arm64 /usr/local/bin/picoclaw
# Initialize configuration
picoclaw onboard
```
### Option 2: Build from Source
```bash
# Install Go 1.21+
wget https://go.dev/dl/go1.23.0.linux-arm64.tar.gz
sudo tar -C /usr/local -xzf go1.23.0.linux-arm64.tar.gz
export PATH=$PATH:/usr/local/go/bin
# Clone and build
git clone https://github.com/sipeed/picoclaw.git
cd picoclaw
make deps
make build
# Install
sudo make install
```
## Configuration
### Basic Configuration
```bash
# Edit config file
nano ~/.picoclaw/config.json
```
Example configuration:
```json
{
"agents": {
"defaults": {
"workspace": "~/.picoclaw/workspace",
"restrict_to_workspace": true,
"model": "openrouter/anthropic/claude-sonnet-4",
"max_tokens": 4096,
"temperature": 0.7
}
},
"providers": {
"openrouter": {
"api_key": "sk-or-v1-your-key-here"
}
},
"channels": {
"telegram": {
"enabled": true,
"token": "YOUR_BOT_TOKEN",
"allow_from": ["YOUR_USER_ID"]
}
},
"gateway": {
"host": "0.0.0.0",
"port": 18790
},
"heartbeat": {
"enabled": true,
"interval": 30
}
}
```
### Environment Variables
```bash
# Add to ~/.bashrc
export PICOCLAW_PROVIDERS_OPENROUTER_API_KEY="sk-or-v1-your-key-here"
export PICOCLAW_AGENTS_DEFAULTS_MODEL="openrouter/anthropic/claude-sonnet-4"
```
## Running as a Service
### Create Dedicated User
```bash
sudo useradd -r -s /bin/false -d /var/lib/picoclaw picoclaw
sudo mkdir -p /var/lib/picoclaw/workspace
sudo chown -R picoclaw:picoclaw /var/lib/picoclaw
```
### Create Systemd Service
```bash
sudo tee /etc/systemd/system/picoclaw.service << 'EOF'
[Unit]
Description=PicoClaw AI Assistant
After=network.target
Wants=network-online.target
[Service]
Type=simple
User=picoclaw
Group=picoclaw
WorkingDirectory=/var/lib/picoclaw
ExecStart=/usr/local/bin/picoclaw gateway
Restart=on-failure
RestartSec=10
# Environment
Environment=PICOCLAW_CONFIG=/etc/picoclaw/config.json
# Security
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/var/lib/picoclaw
PrivateTmp=true
[Install]
WantedBy=multi-user.target
EOF
```
### Configure for Service
```bash
# Move config to system location
sudo mkdir -p /etc/picoclaw
sudo cp ~/.picoclaw/config.json /etc/picoclaw/
sudo chown picoclaw:picoclaw /etc/picoclaw/config.json
sudo chmod 600 /etc/picoclaw/config.json
# Enable and start
sudo systemctl daemon-reload
sudo systemctl enable picoclaw
sudo systemctl start picoclaw
# Check status
sudo systemctl status picoclaw
```
## Hardware-Specific Features
### GPIO Access
Enable GPIO tools for home automation:
```json
{
"tools": {
"exec": {
"enable_deny_patterns": true,
"custom_deny_patterns": []
}
}
}
```
Use with gpiod:
```bash
# Install gpiod tools
sudo apt install gpiod
# Example: Read GPIO pin
gpioget gpiochip0 17
# Example: Set GPIO pin
gpioset gpiochip0 18=1
```
### Temperature Monitoring
```bash
# CPU temperature
vcgencmd measure_temp
# Add to PicoClaw skills or use in exec commands
```
### Camera Module
```bash
# Enable camera
sudo raspi-config
# Navigate to Interface Options > Camera
# Test camera
libcamera-hello
# Capture image
libcamera-still -o image.jpg
```
### Sense HAT
```bash
# Install Sense HAT library
sudo apt install sense-hat
# Python script for sensor data
python3 -c "from sense_hat import SenseHat; s = SenseHat(); print(s.get_temperature())"
```
## Performance Optimization
### Memory Allocation
For Pi 4 with 4GB+ RAM:
```bash
# Check current memory split
vcgencmd get_mem gpu
# Reduce GPU memory (headless)
echo "gpu_mem=16" | sudo tee -a /boot/config.txt
```
### CPU Governor
```bash
# Check current governor
cat /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
# Set to performance (may increase power usage)
echo "performance" | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
# Or set to powersave (reduces performance)
echo "powersave" | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
```
### Disable Unused Services
```bash
# Disable Bluetooth if not used
sudo systemctl disable bluetooth
# Disable audio if not used
sudo systemctl disable alsa-state
# Disable printing
sudo systemctl disable cups
```
### Overclocking (Pi 5)
```bash
# Edit /boot/firmware/config.txt (Pi 5)
# Add overclock settings (use with caution)
# over_voltage=6
# arm_freq=3000
```
## Network Configuration
### Static IP
```bash
# Using nmcli
sudo nmcli con mod "Wired connection 1" ipv4.addresses 192.168.1.100/24
sudo nmcli con mod "Wired connection 1" ipv4.gateway 192.168.1.1
sudo nmcli con mod "Wired connection 1" ipv4.dns "8.8.8.8,8.8.4.4"
sudo nmcli con mod "Wired connection 1" ipv4.method manual
sudo nmcli con up "Wired connection 1"
```
### WiFi
```bash
# Connect to WiFi
sudo nmcli dev wifi connect "SSID" password "PASSWORD"
# Or configure manually
sudo tee /etc/wpa_supplicant/wpa_supplicant.conf << 'EOF'
country=US
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
network={
ssid="YourSSID"
psk="YourPassword"
}
EOF
```
### Access Point Mode
Turn your Pi into a WiFi hotspot:
```bash
# Install required packages
sudo apt install hostapd dnsmasq
# Configure static IP for AP
sudo tee -a /etc/dhcpcd.conf << 'EOF'
interface wlan0
static ip_address=192.168.4.1/24
nohook wpa_supplicant
EOF
# Configure DNSMasq
sudo tee /etc/dnsmasq.conf << 'EOF'
interface=wlan0
dhcp-range=192.168.4.2,192.168.4.20,255.255.255.0,24h
domain=picoclaw.local
address=/picoclaw.local/192.168.4.1
EOF
# Configure hostapd
sudo tee /etc/hostapd/hostapd.conf << 'EOF'
interface=wlan0
driver=nl80211
ssid=PicoClaw
hw_mode=g
channel=7
wpa=2
wpa_passphrase=yourpassword
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP CCMP
EOF
# Point to config
sudo tee /etc/default/hostapd << 'EOF'
DAEMON_CONF="/etc/hostapd/hostapd.conf"
EOF
# Enable services
sudo systemctl unmask hostapd
sudo systemctl enable hostapd dnsmasq
sudo reboot
```
## Local LLM Integration
### Ollama Setup
```bash
# Install Ollama
curl -fsSL https://ollama.com/install.sh | sh
# Pull a small model
ollama pull llama3.2:1b
# Configure PicoClaw to use Ollama
# In config.json:
{
"agents": {
"defaults": {
"model": "ollama/llama3.2:1b"
}
},
"providers": {
"ollama": {
"api_base": "http://localhost:11434/v1"
}
}
}
```
### Performance Notes
For running local LLMs on Raspberry Pi:
- Pi 5 with 8GB RAM can run small models (1-3B parameters)
- Use quantized models (q4, q5) for better performance
- Consider using external GPU accelerators for larger models
## Monitoring and Maintenance
### Health Check Script
```bash
#!/bin/bash
# /usr/local/bin/picoclaw-health.sh
# Check service
if ! systemctl is-active --quiet picoclaw; then
echo "PicoClaw service not running"
exit 1
fi
# Check health endpoint
if ! curl -sf http://localhost:18790/health > /dev/null; then
echo "Health check failed"
exit 1
fi
# Check temperature
TEMP=$(vcgencmd measure_temp | grep -oP '\d+')
if [ "$TEMP" -gt 80 ]; then
echo "High temperature: ${TEMP}C"
fi
echo "All checks passed"
exit 0
```
### Log Monitoring
```bash
# View logs
sudo journalctl -u picoclaw -f
# Check for errors
sudo journalctl -u picoclaw -p err
```
### Backup
```bash
# Backup configuration and workspace
sudo tar czf picoclaw-backup-$(date +%Y%m%d).tar.gz \
/etc/picoclaw \
/var/lib/picoclaw
```
## Troubleshooting
### Service Won't Start
```bash
# Check logs
sudo journalctl -u picoclaw -n 100
# Verify binary
which picoclaw
picoclaw version
# Test manually
sudo -u picoclaw /usr/local/bin/picoclaw gateway
```
### Memory Issues
```bash
# Check memory
free -h
# Add swap
sudo dphys-swapfile swapoff
sudo sed -i 's/CONF_SWAPSIZE=100/CONF_SWAPSIZE=512/' /etc/dphys-swapfile
sudo dphys-swapfile setup
sudo dphys-swapfile swapon
```
### Network Issues
```bash
# Check interface
ip addr
# Test connectivity
ping google.com
# Check DNS
nslookup api.openai.com
```
### Thermal Throttling
```bash
# Check temperature
vcgencmd measure_temp
# Check throttling
vcgencmd get_throttled
# If throttled, improve cooling
# - Add heatsink
# - Add fan
# - Ensure good airflow
```
## Resources
- [Raspberry Pi Documentation](https://www.raspberrypi.com/documentation/)
- [Raspberry Pi Forums](https://forums.raspberrypi.com/)
- [PicoClaw GitHub](https://github.com/sipeed/picoclaw)

445
docs/deployment/security.md Normal file
View file

@ -0,0 +1,445 @@
# Production Security Checklist
This guide provides a comprehensive security checklist for deploying PicoClaw in production environments.
## API Key Security
### Storage
- [ ] **Never commit API keys to version control**
- [ ] Store API keys in environment variables or secure secret management
- [ ] Use separate API keys for development and production
- [ ] Rotate API keys regularly (every 90 days recommended)
### File Permissions
```bash
# Set restrictive permissions on config file
chmod 600 ~/.picoclaw/config.json
# For system-wide installation
sudo chmod 600 /etc/picoclaw/config.json
sudo chown picoclaw:picoclaw /etc/picoclaw/config.json
```
### Environment Variables
```bash
# Use environment variables instead of config file for secrets
export PICOCLAW_PROVIDERS_OPENROUTER_API_KEY="sk-or-v1-xxx"
# Or use a secrets file with restricted access
cat > /etc/picoclaw/secrets.env << 'EOF'
PICOCLAW_PROVIDERS_OPENROUTER_API_KEY=sk-or-v1-xxx
EOF
chmod 600 /etc/picoclaw/secrets.env
chown picoclaw:picoclaw /etc/picoclaw/secrets.env
```
### Docker Secrets
When using Docker Swarm or Kubernetes:
```yaml
# Docker Compose with secrets
services:
picoclaw:
secrets:
- openrouter_key
environment:
- PICOCLAW_PROVIDERS_OPENROUTER_API_KEY_FILE=/run/secrets/openrouter_key
secrets:
openrouter_key:
external: true
```
## Network Security
### Firewall Configuration
```bash
# UFW (Ubuntu/Debian)
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow ssh
sudo ufw allow from 10.0.0.0/8 to any port 18790 # Internal only
sudo ufw enable
# iptables
iptables -A INPUT -p tcp --dport 18790 -s 10.0.0.0/8 -j ACCEPT
iptables -A INPUT -p tcp --dport 18790 -j DROP
```
### Reverse Proxy
Use a reverse proxy for TLS termination:
**Nginx:**
```nginx
server {
listen 443 ssl http2;
server_name picoclaw.example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
# Security headers
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
location / {
proxy_pass http://127.0.0.1:18790;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
```
**Caddy (automatic HTTPS):**
```caddyfile
picoclaw.example.com {
reverse_proxy localhost:18790
}
```
### Bind to Localhost
By default, bind to localhost unless you need external access:
```json
{
"gateway": {
"host": "127.0.0.1",
"port": 18790
}
}
```
## Access Control
### Channel Allowlists
Restrict who can interact with your bot:
```json
{
"channels": {
"telegram": {
"enabled": true,
"token": "YOUR_TOKEN",
"allow_from": ["123456789", "987654321"]
},
"discord": {
"enabled": true,
"token": "YOUR_TOKEN",
"allow_from": ["123456789012345678"]
}
}
}
```
### Multi-Factor Authentication
For admin access, consider:
- SSH key authentication only
- VPN requirement for administrative access
- Separate admin network/VLAN
## Workspace Security
### Restrict to Workspace
Always enable workspace restrictions in production:
```json
{
"agents": {
"defaults": {
"restrict_to_workspace": true,
"workspace": "/var/lib/picoclaw/workspace"
}
}
}
```
### Dangerous Command Blocking
Enable and configure command deny patterns:
```json
{
"tools": {
"exec": {
"enable_deny_patterns": true,
"custom_deny_patterns": [
"rm -rf",
"dd if=",
"mkfs",
"shutdown",
"reboot",
"init 0",
"> /dev/sd",
"chmod 777",
"wget.*\\|.*sh",
"curl.*\\|.*sh"
]
}
}
}
```
### Workspace Isolation
For multi-tenant setups, use separate workspaces:
```json
{
"agents": {
"list": [
{
"id": "agent-a",
"workspace": "/var/lib/picoclaw/agent-a",
"restrict_to_workspace": true
},
{
"id": "agent-b",
"workspace": "/var/lib/picoclaw/agent-b",
"restrict_to_workspace": true
}
]
}
}
```
## System Hardening
### Dedicated User
Run PicoClaw as a dedicated non-root user:
```bash
# Create system user
sudo useradd -r -s /bin/false -d /var/lib/picoclaw picoclaw
# Set ownership
sudo chown -R picoclaw:picoclaw /var/lib/picoclaw
```
### Systemd Sandbox
Use systemd security features:
```ini
[Service]
# Basic restrictions
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
PrivateDevices=true
# Advanced restrictions
ProtectKernelTunables=true
ProtectControlGroups=true
ProtectKernelModules=true
ProtectHostname=true
ProtectClock=true
# Network restrictions (if no external network needed)
# RestrictAddressFamilies=AF_UNIX
# System call filtering
SystemCallFilter=@system-service
SystemCallArchitectures=native
# Memory protection
MemoryDenyWriteExecute=true
# Allow workspace access
ReadWritePaths=/var/lib/picoclaw
ReadOnlyPaths=/etc/picoclaw
```
### Docker Security
```yaml
services:
picoclaw:
# Run as non-root (default in official image)
user: "1000:1000"
# Read-only root filesystem
read_only: true
# Drop all capabilities
cap_drop:
- ALL
# Security options
security_opt:
- no-new-privileges:true
# Resource limits
deploy:
resources:
limits:
memory: 512M
cpus: '1.0'
# Temporary filesystem for writable paths
tmpfs:
- /tmp:size=10M,mode=1777
```
## Monitoring and Logging
### Log Configuration
Enable comprehensive logging:
```bash
# View logs
journalctl -u picoclaw -f
# For Docker
docker logs -f picoclaw-gateway
```
### Audit Trail
Log all tool executions:
```bash
# Debug mode shows all tool calls
picoclaw gateway --debug
```
### Monitoring Setup
Monitor key metrics:
```bash
# Process monitoring
[ -f /var/run/picoclaw.pid ] && ps -p $(cat /var/run/picoclaw.pid) > /dev/null
# Health check endpoint
curl -sf http://localhost:18790/health || echo "PicoClaw unhealthy"
# Memory usage
ps -o rss= -p $(pgrep -f "picoclaw gateway") | awk '{print $1/1024 " MB"}'
```
### Log Rotation
Configure log rotation for long-running deployments:
```bash
# /etc/logrotate.d/picoclaw
/var/log/picoclaw/*.log {
daily
rotate 14
compress
delaycompress
missingok
notifempty
create 0640 picoclaw picoclaw
}
```
## Updates and Maintenance
### Regular Updates
- [ ] Update PicoClaw regularly for security patches
- [ ] Subscribe to release notifications
- [ ] Test updates in staging before production
```bash
# Check current version
picoclaw version
# Update binary
wget https://github.com/sipeed/picoclaw/releases/latest/download/picoclaw-linux-amd64
chmod +x picoclaw-linux-amd64
sudo mv picoclaw-linux-amd64 /usr/local/bin/picoclaw
```
### Dependency Updates
For source installations:
```bash
# Update Go dependencies
make update-deps
make build
```
### Backup Strategy
```bash
# Backup configuration and workspace
tar czf picoclaw-backup-$(date +%Y%m%d).tar.gz \
/etc/picoclaw \
/var/lib/picoclaw
# Store backups securely (encrypted)
gpg -c picoclaw-backup-$(date +%Y%m%d).tar.gz
```
## Security Checklist Summary
### Before Deployment
- [ ] API keys stored securely (not in config committed to git)
- [ ] Config file has restrictive permissions (600)
- [ ] Running as non-root user
- [ ] Workspace restriction enabled
- [ ] Command deny patterns enabled
- [ ] Channel allowlists configured
- [ ] Firewall configured
- [ ] HTTPS enabled (if external access needed)
### After Deployment
- [ ] Health check endpoint accessible
- [ ] Logs being captured
- [ ] Monitoring configured
- [ ] Backup strategy in place
- [ ] Update schedule established
### Regular Maintenance
- [ ] Rotate API keys (every 90 days)
- [ ] Review access logs
- [ ] Apply security updates
- [ ] Test backup restoration
- [ ] Audit user access
## Incident Response
### If API Key is Compromised
1. Immediately revoke the compromised key at the provider
2. Generate a new key
3. Update configuration
4. Restart PicoClaw
5. Review logs for unauthorized usage
### If System is Compromised
1. Isolate the system from network
2. Preserve logs for investigation
3. Revoke all API keys
4. Rebuild from clean backup
5. Update all credentials
6. Review and patch vulnerability
## Additional Resources
- [CIS Benchmarks](https://www.cisecurity.org/cis-benchmarks/)
- [OWASP Security Guidelines](https://owasp.org/www-project-web-security-testing-guide/)
- [Linux Hardening Guide](https://madaidans-insecurities.github.io/guides/linux-hardening.html)

505
docs/deployment/systemd.md Normal file
View file

@ -0,0 +1,505 @@
# Running PicoClaw as a Systemd Service
This guide explains how to run PicoClaw as a systemd service on Linux systems. This is the recommended approach for production deployments on servers and single-board computers.
## Prerequisites
- Linux system with systemd
- Root/sudo access
- PicoClaw binary installed
## Installation
### Step 1: Install the Binary
```bash
# Download the binary
wget https://github.com/sipeed/picoclaw/releases/latest/download/picoclaw-linux-amd64
chmod +x picoclaw-linux-amd64
sudo mv picoclaw-linux-amd64 /usr/local/bin/picoclaw
# Or build from source
git clone https://github.com/sipeed/picoclaw.git
cd picoclaw
make deps
make build
sudo make install
```
### Step 2: Create a Dedicated User
Create a system user for running PicoClaw:
```bash
sudo useradd -r -s /bin/false -d /var/lib/picoclaw picoclaw
```
### Step 3: Create Configuration Directory
```bash
# Create config directory
sudo mkdir -p /etc/picoclaw
# Create workspace directory
sudo mkdir -p /var/lib/picoclaw/workspace
# Set ownership
sudo chown -R picoclaw:picoclaw /var/lib/picoclaw
```
### Step 4: Initialize Configuration
```bash
# Run onboard as the picoclaw user
sudo -u picoclaw /usr/local/bin/picoclaw onboard
# Or create config manually
sudo tee /etc/picoclaw/config.json > /dev/null <<'EOF'
{
"agents": {
"defaults": {
"workspace": "/var/lib/picoclaw/workspace",
"model": "openrouter/anthropic/claude-opus-4-5"
}
},
"providers": {
"openrouter": {
"api_key": "sk-or-v1-your-key-here"
}
},
"gateway": {
"host": "0.0.0.0",
"port": 18790
}
}
EOF
sudo chown picoclaw:picoclaw /etc/picoclaw/config.json
sudo chmod 600 /etc/picoclaw/config.json
```
## Systemd Service File
### Basic Service
Create `/etc/systemd/system/picoclaw.service`:
```ini
[Unit]
Description=PicoClaw AI Assistant Gateway
After=network.target
Wants=network-online.target
[Service]
Type=simple
User=picoclaw
Group=picoclaw
ExecStart=/usr/local/bin/picoclaw gateway
Restart=on-failure
RestartSec=5
# Environment
Environment=PICOCLAW_CONFIG=/etc/picoclaw/config.json
# Security hardening
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/var/lib/picoclaw
PrivateTmp=true
# Logging
StandardOutput=journal
StandardError=journal
SyslogIdentifier=picoclaw
[Install]
WantedBy=multi-user.target
```
### Service with Environment Variables
For using environment variables instead of config file:
```ini
[Unit]
Description=PicoClaw AI Assistant Gateway
After=network.target
Wants=network-online.target
[Service]
Type=simple
User=picoclaw
Group=picoclaw
ExecStart=/usr/local/bin/picoclaw gateway
Restart=on-failure
RestartSec=5
# Environment variables
Environment="PICOCLAW_AGENTS_DEFAULTS_MODEL=openrouter/anthropic/claude-opus-4-5"
Environment="PICOCLAW_PROVIDERS_OPENROUTER_API_KEY=sk-or-v1-your-key-here"
Environment="PICOCLAW_HEARTBEAT_ENABLED=true"
Environment="PICOCLAW_HEARTBEAT_INTERVAL=30"
# Security hardening
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/var/lib/picoclaw
PrivateTmp=true
[Install]
WantedBy=multi-user.target
```
### Production Service with Full Hardening
```ini
[Unit]
Description=PicoClaw AI Assistant Gateway
Documentation=https://github.com/sipeed/picoclaw
After=network.target network-online.target
Wants=network-online.target
[Service]
Type=simple
User=picoclaw
Group=picoclaw
WorkingDirectory=/var/lib/picoclaw
# Main command
ExecStart=/usr/local/bin/picoclaw gateway
ExecReload=/bin/kill -HUP $MAINPID
# Restart policy
Restart=on-failure
RestartSec=5
TimeoutStartSec=30
TimeoutStopSec=30
# Environment
Environment=PICOCLAW_CONFIG=/etc/picoclaw/config.json
Environment=PICOCLAW_WORKSPACE=/var/lib/picoclaw/workspace
# Resource limits
LimitNOFILE=65536
MemoryMax=512M
MemoryHigh=400M
# Security hardening
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
ProtectKernelTunables=true
ProtectControlGroups=true
ProtectKernelModules=true
ProtectHostname=true
ProtectClock=true
ProtectProc=invisible
ProcSubset=pid
PrivateTmp=true
PrivateDevices=true
PrivateUsers=true
PrivateMounts=true
CapabilityBoundingSet=
AmbientCapabilities=
LockPersonality=true
RestrictNamespaces=true
RestrictRealtime=true
RestrictSUIDSGID=true
RestrictAddressFamilies=AF_INET AF_INET6
SystemCallFilter=@system-service
SystemCallArchitectures=native
MemoryDenyWriteExecute=true
# Allow access to workspace
ReadWritePaths=/var/lib/picoclaw
ReadOnlyPaths=/etc/picoclaw
# Logging
StandardOutput=journal
StandardError=journal
SyslogIdentifier=picoclaw
[Install]
WantedBy=multi-user.target
```
## Managing the Service
### Enable and Start
```bash
# Reload systemd to pick up new service
sudo systemctl daemon-reload
# Enable to start on boot
sudo systemctl enable picoclaw
# Start the service
sudo systemctl start picoclaw
# Check status
sudo systemctl status picoclaw
```
### Common Operations
```bash
# Stop the service
sudo systemctl stop picoclaw
# Restart the service
sudo systemctl restart picoclaw
# Disable from starting on boot
sudo systemctl disable picoclaw
# View status
sudo systemctl status picoclaw
# Check if enabled
systemctl is-enabled picoclaw
```
### Viewing Logs
```bash
# View recent logs
sudo journalctl -u picoclaw
# Follow logs in real-time
sudo journalctl -u picoclaw -f
# Last 100 lines
sudo journalctl -u picoclaw -n 100
# Logs from last hour
sudo journalctl -u picoclaw --since "1 hour ago"
# Logs since boot
sudo journalctl -u picoclaw -b
# With priority filtering
sudo journalctl -u picoclaw -p err
```
## Configuration Management
### Using Config File with Symlink
Link the default config location to `/etc/picoclaw/config.json`:
```bash
# Remove default config location
sudo rm -rf /home/picoclaw/.picoclaw
# Create symlink
sudo ln -s /etc/picoclaw /home/picoclaw/.picoclaw
```
### Using Environment File
Create `/etc/picoclaw/picoclaw.env`:
```bash
PICOCLAW_AGENTS_DEFAULTS_MODEL=openrouter/anthropic/claude-opus-4-5
PICOCLAW_PROVIDERS_OPENROUTER_API_KEY=sk-or-v1-your-key-here
PICOCLAW_CHANNELS_TELEGRAM_ENABLED=true
PICOCLAW_CHANNELS_TELEGRAM_TOKEN=123456:ABC
PICOCLAW_HEARTBEAT_ENABLED=true
PICOCLAW_HEARTBEAT_INTERVAL=30
```
Update service file:
```ini
[Service]
EnvironmentFile=/etc/picoclaw/picoclaw.env
```
### Secure API Key Storage
Store API keys in a separate file with restricted permissions:
```bash
# Create secrets file
sudo tee /etc/picoclaw/secrets.env > /dev/null <<'EOF'
PICOCLAW_PROVIDERS_OPENROUTER_API_KEY=sk-or-v1-your-key-here
PICOCLAW_PROVIDERS_OPENAI_API_KEY=sk-your-key-here
EOF
# Restrict permissions
sudo chmod 600 /etc/picoclaw/secrets.env
sudo chown picoclaw:picoclaw /etc/picoclaw/secrets.env
```
## Multiple Instances
### Running Multiple Agents
Create separate service files for different agents:
`/etc/systemd/system/picoclaw-telegram.service`:
```ini
[Unit]
Description=PicoClaw Telegram Bot
After=network.target
[Service]
Type=simple
User=picoclaw
Group=picoclaw
ExecStart=/usr/local/bin/picoclaw gateway
Environment=PICOCLAW_CONFIG=/etc/picoclaw/telegram.json
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
```
`/etc/systemd/system/picoclaw-discord.service`:
```ini
[Unit]
Description=PicoClaw Discord Bot
After=network.target
[Service]
Type=simple
User=picoclaw
Group=picoclaw
ExecStart=/usr/local/bin/picoclaw gateway
Environment=PICOCLAW_CONFIG=/etc/picoclaw/discord.json
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
```
Enable both:
```bash
sudo systemctl daemon-reload
sudo systemctl enable picoclaw-telegram picoclaw-discord
sudo systemctl start picoclaw-telegram picoclaw-discord
```
## Updates and Maintenance
### Updating the Binary
```bash
# Stop service
sudo systemctl stop picoclaw
# Download new version
wget https://github.com/sipeed/picoclaw/releases/latest/download/picoclaw-linux-amd64
chmod +x picoclaw-linux-amd64
sudo mv picoclaw-linux-amd64 /usr/local/bin/picoclaw
# Start service
sudo systemctl start picoclaw
# Verify
sudo systemctl status picoclaw
```
### Backup Configuration
```bash
# Backup config and workspace
sudo tar czf picoclaw-backup-$(date +%Y%m%d).tar.gz \
/etc/picoclaw \
/var/lib/picoclaw
```
### Health Check Script
Create `/usr/local/bin/picoclaw-health-check.sh`:
```bash
#!/bin/bash
# Health check script for PicoClaw
HEALTH_URL="http://localhost:18790/health"
TIMEOUT=5
if curl -sf --max-time $TIMEOUT "$HEALTH_URL" > /dev/null; then
echo "PicoClaw is healthy"
exit 0
else
echo "PicoClaw health check failed"
exit 1
fi
```
Add to systemd timer or cron:
```bash
# Add to cron
*/5 * * * * /usr/local/bin/picoclaw-health-check.sh || systemctl restart picoclaw
```
## Troubleshooting
### Service Fails to Start
```bash
# Check service status
sudo systemctl status picoclaw
# View logs
sudo journalctl -u picoclaw -n 50
# Check if binary exists and is executable
ls -la /usr/local/bin/picoclaw
# Check config file
sudo -u picoclaw cat /etc/picoclaw/config.json
# Test running manually
sudo -u picoclaw /usr/local/bin/picoclaw gateway
```
### Permission Issues
```bash
# Check ownership
ls -la /etc/picoclaw/
ls -la /var/lib/picoclaw/
# Fix ownership
sudo chown -R picoclaw:picoclaw /var/lib/picoclaw
sudo chown picoclaw:picoclaw /etc/picoclaw/config.json
# Check config permissions
sudo chmod 600 /etc/picoclaw/config.json
```
### Network Issues
```bash
# Check if port is listening
sudo ss -tlnp | grep 18790
# Check firewall
sudo ufw status
sudo iptables -L -n
# Test health endpoint
curl http://localhost:18790/health
```
### Reset Service
```bash
# Full reset
sudo systemctl stop picoclaw
sudo systemctl reset-failed picoclaw
sudo systemctl daemon-reload
sudo systemctl start picoclaw
```

501
docs/deployment/termux.md Normal file
View file

@ -0,0 +1,501 @@
# Android/Termux Deployment
PicoClaw can run on Android devices using Termux, allowing you to repurpose old phones or tablets as AI assistants. This is an excellent way to give new life to unused Android devices.
## Prerequisites
- Android 7.0 or later
- Termux app (from F-Droid recommended)
- ARM64 Android device (most devices from 2015+)
## Installing Termux
### Option 1: F-Droid (Recommended)
The F-Droid version is more up-to-date and doesn't have Google Play restrictions:
1. Install [F-Droid](https://f-droid.org/)
2. Search for "Termux" in F-Droid
3. Install Termux, Termux:API (optional)
### Option 2: GitHub Releases
Download directly from [Termux GitHub releases](https://github.com/termux/termux-app/releases):
1. Download the latest APK
2. Enable "Install from unknown sources" in Android settings
3. Install the APK
### Important Note
**Do not install Termux from Google Play Store.** That version is outdated and has compatibility issues. Use F-Droid or GitHub releases instead.
## Initial Setup
### Step 1: Update Termux Packages
Open Termux and run:
```bash
# Update package lists
pkg update && pkg upgrade -y
# Install essential packages
pkg install wget curl git proot -y
```
### Step 2: Download PicoClaw
```bash
# Navigate to home directory
cd ~
# Download the ARM64 binary
wget https://github.com/sipeed/picoclaw/releases/latest/download/picoclaw-linux-arm64
# Make executable
chmod +x picoclaw-linux-arm64
```
### Step 3: Initialize with proot
Termux has a different filesystem layout than standard Linux. Use `proot` to run PicoClaw:
```bash
# Install proot if not already installed
pkg install proot -y
# Initialize PicoClaw using termux-chroot
termux-chroot ./picoclaw-linux-arm64 onboard
```
### Step 4: Configure PicoClaw
```bash
# Edit configuration
termux-chroot nano ~/.picoclaw/config.json
```
Add your API keys:
```json
{
"agents": {
"defaults": {
"model": "openrouter/anthropic/claude-opus-4-5"
}
},
"providers": {
"openrouter": {
"api_key": "sk-or-v1-your-key-here"
}
}
}
```
## Running PicoClaw
### Agent Mode (One-Shot Queries)
```bash
# Run a single query
termux-chroot ./picoclaw-linux-arm64 agent -m "What is the weather today?"
# Interactive mode
termux-chroot ./picoclaw-linux-arm64 agent
# Debug mode
termux-chroot ./picoclaw-linux-arm64 agent --debug -m "Hello"
```
### Gateway Mode (Always-On Bot)
```bash
# Start gateway
termux-chroot ./picoclaw-linux-arm64 gateway
```
## Creating a Shortcut Script
Create a helper script for easier execution:
```bash
# Create script
cat > $PREFIX/bin/picoclaw << 'EOF'
#!/data/data/com.termux/files/usr/bin/sh
# PicoClaw wrapper for Termux
BINARY="$HOME/picoclaw-linux-arm64"
if [ ! -f "$BINARY" ]; then
echo "PicoClaw binary not found at $BINARY"
exit 1
fi
termux-chroot "$BINARY" "$@"
EOF
# Make executable
chmod +x $PREFIX/bin/picoclaw
```
Now you can run PicoClaw directly:
```bash
picoclaw agent -m "Hello"
picoclaw gateway
```
## Keeping PicoClaw Running
### Using tmux
Run PicoClaw in a persistent session:
```bash
# Install tmux
pkg install tmux -y
# Create new session
tmux new -s picoclaw
# Start PicoClaw
picoclaw gateway
# Detach: Press Ctrl+B then D
# Reattach later
tmux attach -t picoclaw
```
### Using nohup
Run in background:
```bash
# Start in background
nohup picoclaw gateway > picoclaw.log 2>&1 &
# View logs
tail -f picoclaw.log
# Find process ID
pgrep -f picoclaw
# Stop
pkill -f picoclaw
```
### Auto-Start on Boot
Create a boot script using Termux:Boot (requires Termux:API):
```bash
# Install Termux:API and Termux:Boot from F-Droid
# Create boot directory
mkdir -p ~/.termux/boot
# Create boot script
cat > ~/.termux/boot/picoclaw.sh << 'EOF'
#!/data/data/com.termux/files/usr/bin/sh
# Auto-start PicoClaw on boot
# Wait for network
sleep 30
# Start in tmux session
tmux new -d -s picoclaw "picoclaw gateway"
EOF
# Make executable
chmod +x ~/.termux/boot/picoclaw.sh
```
## Battery Optimization
### Disable Battery Optimization
To prevent Android from killing Termux in the background:
1. Go to Settings > Battery > Battery Optimization
2. Find Termux and select "Don't optimize"
3. Also disable battery optimization for Termux:API and Termux:Boot if installed
### Acquire Wakelock
Prevent the device from sleeping:
```bash
# Install Termux:API first
pkg install termux-api -y
# Acquire wakelock
termux-wake-lock
# Release wakelock when done
termux-wake-unlock
```
### Notification (Keep Alive)
Termux shows a persistent notification when running:
```bash
# The notification is shown automatically
# To start foreground service:
termux-notification --ongoing --title "PicoClaw" --content "Running..."
```
## Storage Access
### Access Shared Storage
To access files in your Android shared storage:
```bash
# Request storage permission
termux-setup-storage
# This creates a symlink at ~/storage
# Access Downloads: ~/storage/downloads
# Access DCIM: ~/storage/dcim
# Access Documents: ~/storage/documents
```
### Use Shared Storage for Workspace
Configure PicoClaw to use shared storage:
```json
{
"agents": {
"defaults": {
"workspace": "/data/data/com.termux/files/home/storage/documents/picoclaw"
}
}
}
```
## Notifications
Send notifications when PicoClaw completes tasks:
```bash
# Simple notification
termux-notification --title "PicoClaw" --content "Task completed"
# With sound
termux-notification --title "PicoClaw" --content "Task completed" --sound
# With action button
termux-notification --title "PicoClaw" --content "New message" --button1 "View" --button1-action "termux-open-url https://example.com"
```
## Hardware Integration
### Camera Access
Use Termux:API to access the camera:
```bash
# Take a photo
termux-camera-photo ~/photo.jpg
# Use in PicoClaw skills or tools
```
### Sensors
Access device sensors:
```bash
# Get sensor list
termux-sensor -l
# Get sensor data
termux-sensor -s "accelerometer"
```
### Location
Get GPS location:
```bash
# Get current location
termux-location
```
### Text-to-Speech
Have PicoClaw speak responses:
```bash
# Install TTS
pkg install espeak -y
# Speak text
espeak "Hello from PicoClaw"
```
Or use Termux:API TTS:
```bash
termux-tts-speak "Hello from PicoClaw"
```
## Performance Optimization
### Memory Management
Older Android devices may have limited RAM:
```bash
# Check available memory
free -h
# Kill unnecessary processes
pkill -f zygote
# Reduce memory usage in config
# Set lower max_tokens
```
### CPU Throttling
Prevent thermal throttling:
1. Remove phone case for better cooling
2. Reduce screen brightness
3. Disable unnecessary apps
### Network Optimization
For stable network on mobile data:
```bash
# Keep connection alive with periodic ping
while true; do ping -c 1 google.com; sleep 60; done &
```
## Troubleshooting
### Binary Won't Execute
```bash
# Check architecture
uname -m
# Should show aarch64
# Verify binary is for ARM64
file picoclaw-linux-arm64
# Check permissions
ls -la picoclaw-linux-arm64
chmod +x picoclaw-linux-arm64
```
### proot Errors
```bash
# Update proot
pkg upgrade proot
# Try alternative proot command
proot ./picoclaw-linux-arm64 onboard
```
### Network Issues
```bash
# Check network
ping google.com
# Check DNS
nslookup api.openai.com
# Test with curl
curl -I https://api.openai.com
```
### Permission Denied
```bash
# Reset Termux permissions in Android settings
# Settings > Apps > Termux > Permissions
# Re-run setup
termux-setup-storage
```
### App Killed in Background
1. Disable battery optimization for Termux
2. Use `termux-wake-lock`
3. Keep the notification visible
4. Use tmux for persistent sessions
### Clear Everything and Start Fresh
```bash
# Remove PicoClaw
rm -rf ~/.picoclaw
rm picoclaw-linux-arm64
# Re-download and setup
wget https://github.com/sipeed/picoclaw/releases/latest/download/picoclaw-linux-arm64
chmod +x picoclaw-linux-arm64
termux-chroot ./picoclaw-linux-arm64 onboard
```
## Use Cases
### Home Automation Hub
Run PicoClaw as a Telegram bot to control smart home devices:
```json
{
"channels": {
"telegram": {
"enabled": true,
"token": "YOUR_BOT_TOKEN"
}
}
}
```
### Always-On Assistant
Keep PicoClaw running 24/7 on an old phone:
1. Enable wake lock
2. Disable battery optimization
3. Use tmux for persistence
4. Connect to charger
### Mobile AI Companion
Use PicoClaw with voice input/output:
```bash
# Create voice assistant script
cat > ~/voice-assist.sh << 'EOF'
#!/data/data/com.termux/files/usr/bin/sh
echo "Listening..."
RECORDING=$(mktemp /tmp/recording.XXXXXX.wav)
termux-speech-to-text > /tmp/text.txt
TEXT=$(cat /tmp/text.txt)
echo "You said: $TEXT"
RESPONSE=$(picoclaw agent -m "$TEXT")
echo "Response: $RESPONSE"
termux-tts-speak "$RESPONSE"
EOF
chmod +x ~/voice-assist.sh
```
## Resources
- [Termux Wiki](https://wiki.termux.com/)
- [Termux GitHub](https://github.com/termux)
- [PicoClaw Releases](https://github.com/sipeed/picoclaw/releases)

View file

@ -0,0 +1,126 @@
# PicoClaw Developer Guide
Welcome to the PicoClaw Developer Guide. This documentation is intended for developers who want to understand, extend, or contribute to PicoClaw.
## Overview
PicoClaw is an ultra-lightweight AI assistant written in Go. It follows a message bus architecture where channels (Telegram, Discord, etc.) publish inbound messages and subscribe to outbound responses.
## Documentation Sections
### Getting Started
- [Building from Source](building.md) - How to build PicoClaw from source code
- [Running Tests](testing.md) - How to run the test suite
- [Code Style Guide](code-style.md) - Coding conventions and style guidelines
### Architecture
- [System Architecture](architecture.md) - Overview of PicoClaw's architecture and components
- [Data Flow](data-flow.md) - Understanding the message bus and data flow
### Contributing
- [Contribution Guidelines](contributing.md) - How to contribute to PicoClaw
### Extending PicoClaw
The [extending/](extending/) directory contains guides for extending PicoClaw:
- [Creating Custom Tools](extending/creating-tools.md) - How to create custom tools
- [Creating LLM Providers](extending/creating-providers.md) - How to create new LLM provider implementations
- [Creating Channel Integrations](extending/creating-channels.md) - How to create new channel integrations
- [Creating Skills](extending/creating-skills.md) - How to create custom skills
### API Reference
The [api/](api/) directory contains API reference documentation:
- [Tool Interface](api/tool-interface.md) - Tool interface reference
- [Provider Interface](api/provider-interface.md) - LLMProvider interface reference
- [Message Bus API](api/message-bus.md) - Message bus API reference
- [Session API](api/session-api.md) - Session manager API reference
## Quick Start for Developers
```bash
# Clone the repository
git clone https://github.com/sipeed/picoclaw.git
cd picoclaw
# Install dependencies
make deps
# Build
make build
# Run tests
make test
# Run the agent
./build/picoclaw agent -m "Hello, PicoClaw!"
```
## Key Concepts
### Message Bus Architecture
PicoClaw uses a message bus pattern for communication between components:
1. **Channels** receive messages from external platforms (Telegram, Discord, etc.)
2. Messages are published to the **inbound** bus
3. The **AgentLoop** consumes messages from the bus
4. Responses are published to the **outbound** bus
5. Channels subscribe to outbound messages and send them to their platforms
### Tool System
Tools are the primary way PicoClaw interacts with the world. Each tool:
- Implements the `Tool` interface with `Name()`, `Description()`, `Parameters()`, and `Execute()` methods
- Can optionally implement `ContextualTool` for channel context
- Can optionally implement `AsyncTool` for asynchronous operations
### LLM Provider System
Providers handle communication with LLM APIs. Each provider:
- Implements the `LLMProvider` interface with `Chat()` and `GetDefaultModel()` methods
- Handles request/response transformation for specific APIs
- Supports tool calling for agentic behavior
### Session Management
Sessions track conversation history:
- Each session has a unique key (typically "channel:chatID")
- Messages are stored in memory and persisted to disk
- Automatic summarization when history exceeds thresholds
## Project Structure
```
picoclaw/
├── cmd/picoclaw/ # CLI entry point
├── pkg/
│ ├── agent/ # Core agent logic
│ ├── bus/ # Message bus implementation
│ ├── channels/ # Platform integrations
│ ├── providers/ # LLM provider implementations
│ ├── tools/ # Tool implementations
│ ├── session/ # Session management
│ ├── config/ # Configuration handling
│ ├── skills/ # Skill loading system
│ └── ... # Other packages
├── docs/ # Documentation
└── Makefile # Build commands
```
## Getting Help
- GitHub Issues: https://github.com/sipeed/picoclaw/issues
- Source Code: https://github.com/sipeed/picoclaw
## License
PicoClaw is licensed under the MIT License.

View file

@ -0,0 +1,222 @@
# API Reference
This directory contains reference documentation for PicoClaw's core APIs.
## Overview
PicoClaw provides several key APIs for extending and integrating with the system:
| API | Description | Documentation |
|-----|-------------|---------------|
| Tool Interface | Create tools for agent capabilities | [tool-interface.md](tool-interface.md) |
| Provider Interface | Implement LLM provider integrations | [provider-interface.md](provider-interface.md) |
| Message Bus | Async message passing system | [message-bus.md](message-bus.md) |
| Session Manager | Conversation history management | [session-api.md](session-api.md) |
## Core Types
### Message Types
```go
// Inbound message from external platform
type InboundMessage struct {
Channel string
SenderID string
ChatID string
Content string
Media []string
SessionKey string
Metadata map[string]string
}
// Outbound message to external platform
type OutboundMessage struct {
Channel string
ChatID string
Content string
}
```
### LLM Types
```go
// Message for LLM conversation
type Message struct {
Role string
Content string
ToolCalls []ToolCall
ToolCallID string
}
// LLM response
type LLMResponse struct {
Content string
ToolCalls []ToolCall
FinishReason string
Usage *UsageInfo
}
// Tool definition for LLM
type ToolDefinition struct {
Type string
Function ToolFunctionDefinition
}
```
### Tool Types
```go
// Tool result from execution
type ToolResult struct {
ForLLM string
ForUser string
Silent bool
IsError bool
Async bool
Err error
}
```
## Package Overview
### pkg/tools
Tool system for agent capabilities.
Key types:
- `Tool` - Base tool interface
- `ContextualTool` - Tools with channel context
- `AsyncTool` - Asynchronous tools
- `ToolResult` - Execution results
- `ToolRegistry` - Tool management
### pkg/providers
LLM provider implementations.
Key types:
- `LLMProvider` - Provider interface
- `Message` - Conversation message
- `LLMResponse` - LLM response
- `FailoverError` - Error with classification
- `FallbackChain` - Model fallback logic
### pkg/bus
Message bus for async communication.
Key types:
- `MessageBus` - Bus implementation
- `InboundMessage` - Incoming messages
- `OutboundMessage` - Outgoing messages
### pkg/session
Session and history management.
Key types:
- `Session` - Conversation session
- `SessionManager` - Session management
### pkg/channels
Platform integrations.
Key types:
- `Channel` - Channel interface
- `BaseChannel` - Common functionality
### pkg/skills
Skill loading system.
Key types:
- `SkillsLoader` - Skill discovery
- `SkillInfo` - Skill metadata
## Quick Reference
### Implementing a Tool
```go
type MyTool struct{}
func (t *MyTool) Name() string { return "my-tool" }
func (t *MyTool) Description() string { return "Does something" }
func (t *MyTool) Parameters() map[string]interface{} {
return map[string]interface{}{
"type": "object",
"properties": map[string]interface{}{
"input": map[string]interface{}{"type": "string"},
},
"required": []string{"input"},
}
}
func (t *MyTool) Execute(ctx context.Context, args map[string]interface{}) *ToolResult {
return UserResult("Result")
}
```
### Implementing a Provider
```go
type MyProvider struct{}
func (p *MyProvider) Chat(ctx context.Context, messages []Message,
tools []ToolDefinition, model string,
options map[string]interface{}) (*LLMResponse, error) {
// Implementation
}
func (p *MyProvider) GetDefaultModel() string {
return "my-model"
}
```
### Using the Message Bus
```go
bus := bus.NewMessageBus()
// Publish inbound
bus.PublishInbound(bus.InboundMessage{
Channel: "telegram",
ChatID: "123",
Content: "Hello",
})
// Consume inbound
msg, ok := bus.ConsumeInbound(ctx)
// Publish outbound
bus.PublishOutbound(bus.OutboundMessage{
Channel: "telegram",
ChatID: "123",
Content: "Hi there!",
})
```
### Using Session Manager
```go
sm := session.NewSessionManager(storagePath)
// Get or create session
session := sm.GetOrCreate("telegram:123")
// Add message
sm.AddMessage("telegram:123", "user", "Hello")
// Get history
history := sm.GetHistory("telegram:123")
// Save
sm.Save("telegram:123")
```
## See Also
- [Creating Tools](../extending/creating-tools.md)
- [Creating Providers](../extending/creating-providers.md)
- [Creating Channels](../extending/creating-channels.md)
- [Architecture Overview](../architecture.md)

View file

@ -0,0 +1,490 @@
# Message Bus API Reference
This document provides detailed reference for the Message Bus API.
## Overview
The Message Bus is the central communication hub in PicoClaw. It enables asynchronous communication between channels and the agent loop.
## Types
### MessageBus
The main message bus structure.
```go
type MessageBus struct {
inbound chan InboundMessage
outbound chan OutboundMessage
handlers map[string]MessageHandler
closed bool
mu sync.RWMutex
}
```
### InboundMessage
Message from an external platform.
```go
type InboundMessage struct {
Channel string `json:"channel"`
SenderID string `json:"sender_id"`
ChatID string `json:"chat_id"`
Content string `json:"content"`
Media []string `json:"media,omitempty"`
SessionKey string `json:"session_key"`
Metadata map[string]string `json:"metadata,omitempty"`
}
```
**Fields:**
| Field | Type | Description |
|-------|------|-------------|
| Channel | string | Platform identifier (e.g., "telegram", "discord") |
| SenderID | string | User identifier on the platform |
| ChatID | string | Chat/conversation identifier |
| Content | string | Message text content |
| Media | []string | Optional media URLs or paths |
| SessionKey | string | Optional pre-computed session key |
| Metadata | map[string]string | Platform-specific metadata |
**Common Metadata Keys:**
| Key | Description |
|-----|-------------|
| message_id | Platform message ID |
| reply_to_id | ID of message being replied to |
| peer_kind | "direct", "group", "channel" |
| peer_id | Peer identifier |
| account_id | Bot account identifier |
| guild_id | Discord guild ID |
| team_id | Slack team ID |
### OutboundMessage
Message to be sent to a platform.
```go
type OutboundMessage struct {
Channel string `json:"channel"`
ChatID string `json:"chat_id"`
Content string `json:"content"`
}
```
**Fields:**
| Field | Type | Description |
|-------|------|-------------|
| Channel | string | Target platform |
| ChatID | string | Target chat/conversation |
| Content | string | Message content |
### MessageHandler
Function type for handling inbound messages.
```go
type MessageHandler func(InboundMessage) error
```
## Functions
### NewMessageBus
Creates a new message bus.
```go
func NewMessageBus() *MessageBus
```
**Returns:** New MessageBus with buffered channels (capacity: 100)
```go
bus := bus.NewMessageBus()
```
## Methods
### PublishInbound
Publishes an inbound message to the bus.
```go
func (mb *MessageBus) PublishInbound(msg InboundMessage)
```
**Parameters:**
- `msg`: Message to publish
**Behavior:**
- Non-blocking if channel has capacity
- Silently drops message if bus is closed
```go
bus.PublishInbound(bus.InboundMessage{
Channel: "telegram",
SenderID: "123456",
ChatID: "123456",
Content: "Hello!",
})
```
### ConsumeInbound
Consumes an inbound message from the bus.
```go
func (mb *MessageBus) ConsumeInbound(ctx context.Context) (InboundMessage, bool)
```
**Parameters:**
- `ctx`: Context for cancellation
**Returns:**
- `InboundMessage`: The consumed message
- `bool`: True if message was received, false if context cancelled
```go
msg, ok := bus.ConsumeInbound(ctx)
if !ok {
// Context cancelled
return
}
// Process msg
```
### PublishOutbound
Publishes an outbound message to the bus.
```go
func (mb *MessageBus) PublishOutbound(msg OutboundMessage)
```
**Parameters:**
- `msg`: Message to publish
```go
bus.PublishOutbound(bus.OutboundMessage{
Channel: "telegram",
ChatID: "123456",
Content: "Hi there!",
})
```
### SubscribeOutbound
Subscribes to outbound messages.
```go
func (mb *MessageBus) SubscribeOutbound(ctx context.Context) (OutboundMessage, bool)
```
**Parameters:**
- `ctx`: Context for cancellation
**Returns:**
- `OutboundMessage`: The outbound message
- `bool`: True if message was received, false if context cancelled
```go
for {
msg, ok := bus.SubscribeOutbound(ctx)
if !ok {
break // Context cancelled
}
// Send msg to platform
channel.Send(ctx, msg)
}
```
### RegisterHandler
Registers a handler for a channel.
```go
func (mb *MessageBus) RegisterHandler(channel string, handler MessageHandler)
```
**Parameters:**
- `channel`: Channel name
- `handler`: Handler function
```go
bus.RegisterHandler("telegram", func(msg bus.InboundMessage) error {
// Handle message
return nil
})
```
### GetHandler
Retrieves a handler for a channel.
```go
func (mb *MessageBus) GetHandler(channel string) (MessageHandler, bool)
```
**Parameters:**
- `channel`: Channel name
**Returns:**
- `MessageHandler`: The registered handler
- `bool`: True if handler exists
```go
handler, ok := bus.GetHandler("telegram")
if ok {
handler(msg)
}
```
### Close
Closes the message bus.
```go
func (mb *MessageBus) Close()
```
**Behavior:**
- Closes inbound and outbound channels
- Prevents new messages from being published
- Safe to call multiple times
```go
bus.Close()
```
## Usage Patterns
### Producer (Channel)
Channels publish inbound messages:
```go
type TelegramChannel struct {
bus *bus.MessageBus
}
func (c *TelegramChannel) handleUpdate(update Update) {
c.bus.PublishInbound(bus.InboundMessage{
Channel: "telegram",
SenderID: strconv.FormatInt(update.Message.From.ID, 10),
ChatID: strconv.FormatInt(update.Message.Chat.ID, 10),
Content: update.Message.Text,
Metadata: map[string]string{
"message_id": strconv.FormatInt(update.Message.MessageID, 10),
},
})
}
```
### Consumer (Agent Loop)
The agent loop consumes inbound messages:
```go
func (al *AgentLoop) Run(ctx context.Context) error {
for al.running.Load() {
select {
case <-ctx.Done():
return nil
default:
msg, ok := al.bus.ConsumeInbound(ctx)
if !ok {
continue
}
response, err := al.processMessage(ctx, msg)
if err != nil {
response = fmt.Sprintf("Error: %v", err)
}
if response != "" {
al.bus.PublishOutbound(bus.OutboundMessage{
Channel: msg.Channel,
ChatID: msg.ChatID,
Content: response,
})
}
}
}
return nil
}
```
### Subscriber (Gateway)
Gateways subscribe to outbound messages:
```go
func (g *Gateway) runOutboundLoop(ctx context.Context) {
for {
select {
case <-ctx.Done():
return
default:
msg, ok := g.bus.SubscribeOutbound(ctx)
if !ok {
continue
}
channel, ok := g.channels.GetChannel(msg.Channel)
if !ok {
continue
}
if err := channel.Send(ctx, msg); err != nil {
log.Printf("Failed to send: %v", err)
}
}
}
}
```
## Thread Safety
The MessageBus is thread-safe:
- All operations are protected by mutex
- Multiple goroutines can publish simultaneously
- Multiple goroutines can consume simultaneously
```go
// Safe to call from multiple goroutines
go func() {
bus.PublishInbound(msg1)
}()
go func() {
bus.PublishInbound(msg2)
}()
```
## Buffer Behavior
Channels are buffered with capacity 100:
- Publish is non-blocking until buffer is full
- When buffer is full, publish blocks until space available
- This provides backpressure to prevent memory issues
## Error Handling
### Closed Bus
Operations on a closed bus are safe:
```go
bus.Close()
// Safe - message is dropped
bus.PublishInbound(msg) // No-op
// Safe - returns empty message and false
msg, ok := bus.ConsumeInbound(ctx) // ok == false
```
### Context Cancellation
Consume/Subscribe respect context:
```go
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
msg, ok := bus.ConsumeInbound(ctx)
if !ok {
// Timed out or cancelled
}
```
## Best Practices
### Publishing
1. **Check Context**: Respect context in publishers
2. **Handle Full Buffer**: Be prepared for blocking
3. **Don't Block**: Don't hold locks while publishing
```go
func (c *Channel) publishAsync(msg bus.InboundMessage) {
go func() {
select {
case <-c.ctx.Done():
return
default:
c.bus.PublishInbound(msg)
}
}()
}
```
### Consuming
1. **Use Context**: Always use context for cancellation
2. **Check OK**: Always check the ok return value
3. **Handle Errors**: Process errors gracefully
```go
for {
msg, ok := bus.ConsumeInbound(ctx)
if !ok {
if ctx.Err() != nil {
// Context cancelled
return ctx.Err()
}
// Bus closed
return nil
}
if err := process(msg); err != nil {
// Handle error
}
}
```
### Graceful Shutdown
1. **Stop Publishing**: Stop accepting new messages
2. **Drain Queues**: Process remaining messages
3. **Close Bus**: Close when done
```go
// Stop accepting new messages
stopChannels()
// Drain with timeout
drainCtx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
for {
msg, ok := bus.ConsumeInbound(drainCtx)
if !ok {
break
}
process(msg)
}
cancel()
// Close bus
bus.Close()
```
## Performance Characteristics
| Metric | Value |
|--------|-------|
| Buffer Capacity | 100 messages per channel |
| Memory per Message | ~200 bytes (approximate) |
| Thread Safety | Yes (mutex protected) |
| Blocking | Yes (when buffer full) |
## See Also
- [Data Flow](../data-flow.md)
- [Creating Channels](../extending/creating-channels.md)
- [Bus Implementation](https://github.com/sipeed/picoclaw/tree/main/pkg/bus)

View file

@ -0,0 +1,482 @@
# LLMProvider Interface Reference
This document provides detailed reference for the LLMProvider interface and related types.
## Core Interface
### LLMProvider
The interface that all LLM providers must implement.
```go
type LLMProvider interface {
Chat(ctx context.Context, messages []Message, tools []ToolDefinition,
model string, options map[string]interface{}) (*LLMResponse, error)
GetDefaultModel() string
}
```
### Methods
#### Chat
Sends a chat request to the LLM.
```go
Chat(ctx context.Context, messages []Message, tools []ToolDefinition,
model string, options map[string]interface{}) (*LLMResponse, error)
```
**Parameters:**
| Parameter | Type | Description |
|-----------|------|-------------|
| ctx | context.Context | Context for cancellation and timeout |
| messages | []Message | Conversation history |
| tools | []ToolDefinition | Available tools for function calling |
| model | string | Model identifier (may include provider prefix) |
| options | map[string]interface{} | Additional options (max_tokens, temperature, etc.) |
**Returns:**
| Type | Description |
|------|-------------|
| *LLMResponse | LLM response with content and tool calls |
| error | Error if request failed |
**Common Options:**
| Key | Type | Description |
|-----|------|-------------|
| max_tokens | int | Maximum tokens in response |
| temperature | float64 | Sampling temperature (0-2) |
| top_p | float64 | Nucleus sampling parameter |
| stop | []string | Stop sequences |
#### GetDefaultModel
Returns the default model for this provider.
```go
GetDefaultModel() string
```
**Returns:** Model identifier string (e.g., "openrouter/anthropic/claude-opus-4-5")
## Message Types
### Message
Represents a message in the conversation.
```go
type Message struct {
Role string `json:"role"`
Content string `json:"content"`
ToolCalls []ToolCall `json:"tool_calls,omitempty"`
ToolCallID string `json:"tool_call_id,omitempty"`
}
```
**Fields:**
| Field | Type | Description |
|-------|------|-------------|
| Role | string | "system", "user", "assistant", or "tool" |
| Content | string | Message text content |
| ToolCalls | []ToolCall | Tool calls from assistant |
| ToolCallID | string | ID for tool response messages |
**Roles:**
- `system`: System instructions
- `user`: User message
- `assistant`: LLM response
- `tool`: Tool execution result
### ToolCall
Represents a tool call request from the LLM.
```go
type ToolCall struct {
ID string `json:"id"`
Type string `json:"type,omitempty"`
Function *FunctionCall `json:"function,omitempty"`
Name string `json:"name,omitempty"`
Arguments map[string]interface{} `json:"arguments,omitempty"`
}
```
**Fields:**
| Field | Type | Description |
|-------|------|-------------|
| ID | string | Unique identifier for the tool call |
| Type | string | Usually "function" |
| Function | *FunctionCall | Function call details (for API format) |
| Name | string | Function/tool name |
| Arguments | map[string]interface{} | Parsed arguments |
### FunctionCall
Detailed function call information.
```go
type FunctionCall struct {
Name string `json:"name"`
Arguments string `json:"arguments"` // JSON string
}
```
**Fields:**
| Field | Type | Description |
|-------|------|-------------|
| Name | string | Function name |
| Arguments | string | Arguments as JSON string |
### LLMResponse
Response from the LLM.
```go
type LLMResponse struct {
Content string `json:"content"`
ToolCalls []ToolCall `json:"tool_calls,omitempty"`
FinishReason string `json:"finish_reason"`
Usage *UsageInfo `json:"usage,omitempty"`
}
```
**Fields:**
| Field | Type | Description |
|-------|------|-------------|
| Content | string | Text content of response |
| ToolCalls | []ToolCall | Requested tool calls |
| FinishReason | string | Why generation stopped |
| Usage | *UsageInfo | Token usage information |
**Finish Reasons:**
- `stop`: Natural end of response
- `tool_calls`: LLM requested tool execution
- `length`: Max tokens reached
- `content_filter`: Content policy triggered
### UsageInfo
Token usage statistics.
```go
type UsageInfo struct {
PromptTokens int `json:"prompt_tokens"`
CompletionTokens int `json:"completion_tokens"`
TotalTokens int `json:"total_tokens"`
}
```
**Fields:**
| Field | Type | Description |
|-------|------|-------------|
| PromptTokens | int | Tokens in the prompt |
| CompletionTokens | int | Tokens in the response |
| TotalTokens | int | Total tokens used |
## Tool Definition Types
### ToolDefinition
Defines a tool for the LLM.
```go
type ToolDefinition struct {
Type string `json:"type"`
Function ToolFunctionDefinition `json:"function"`
}
```
### ToolFunctionDefinition
Describes a tool function.
```go
type ToolFunctionDefinition struct {
Name string `json:"name"`
Description string `json:"description"`
Parameters map[string]interface{} `json:"parameters"`
}
```
## Error Handling
### FailoverError
Error with classification for fallback support.
```go
type FailoverError struct {
Reason FailoverReason
Provider string
Model string
Status int
Wrapped error
}
```
**Fields:**
| Field | Type | Description |
|-------|------|-------------|
| Reason | FailoverReason | Classification of the error |
| Provider | string | Provider identifier |
| Model | string | Model being used |
| Status | int | HTTP status code |
| Wrapped | error | Underlying error |
### FailoverReason
Classification of LLM errors.
```go
type FailoverReason string
const (
FailoverAuth FailoverReason = "auth"
FailoverRateLimit FailoverReason = "rate_limit"
FailoverBilling FailoverReason = "billing"
FailoverTimeout FailoverReason = "timeout"
FailoverFormat FailoverReason = "format"
FailoverOverloaded FailoverReason = "overloaded"
FailoverUnknown FailoverReason = "unknown"
)
```
**Reasons:**
| Reason | Description | Retriable |
|--------|-------------|-----------|
| auth | Authentication error | No |
| rate_limit | Rate limited | Yes |
| billing | Billing/quota issue | No |
| timeout | Request timeout | Yes |
| format | Invalid request format | No |
| overloaded | Service overloaded | Yes |
| unknown | Unknown error | Yes |
### Methods
#### Error() string
Returns formatted error message.
```go
func (e *FailoverError) Error() string
// "failover(auth): provider=openrouter model=gpt-4 status=401: ..."
```
#### Unwrap() error
Returns the underlying error.
```go
func (e *FailoverError) Unwrap() error
```
#### IsRetriable() bool
Returns true if the error should trigger fallback.
```go
func (e *FailoverError) IsRetriable() bool
// Returns false for Format errors, true otherwise
```
## Fallback Chain
### ModelConfig
Configuration for primary and fallback models.
```go
type ModelConfig struct {
Primary string
Fallbacks []string
}
```
### FallbackChain
Handles fallback between model candidates.
```go
type FallbackChain struct {
// contains filtered or unexported fields
}
```
#### NewFallbackChain(cooldown *CooldownTracker) *FallbackChain
Creates a new fallback chain.
```go
cooldown := providers.NewCooldownTracker()
fallback := providers.NewFallbackChain(cooldown)
```
#### Execute
Executes with fallback logic.
```go
func (fc *FallbackChain) Execute(ctx context.Context,
candidates []ModelCandidate,
fn func(ctx context.Context, provider, model string) (*LLMResponse, error),
) (*FallbackResult, error)
```
### CooldownTracker
Tracks provider cooldown periods.
```go
type CooldownTracker struct {
// contains filtered or unexported fields
}
```
#### NewCooldownTracker() *CooldownTracker
Creates a new tracker.
```go
tracker := providers.NewCooldownTracker()
```
#### SetCooldown(provider string, duration time.Duration)
Sets a cooldown for a provider.
```go
tracker.SetCooldown("openrouter", 30*time.Second)
```
#### IsOnCooldown(provider string) bool
Checks if provider is on cooldown.
```go
if tracker.IsOnCooldown("openrouter") {
// Skip this provider
}
```
## Model Reference
### ModelRef
Parses and manipulates model references.
Format: `provider/model` or just `model`
```go
// Parse model reference
ref := providers.ParseModelRef("openrouter/anthropic/claude-opus-4-5")
ref.Provider // "openrouter"
ref.Model // "anthropic/claude-opus-4-5"
ref.Full // "openrouter/anthropic/claude-opus-4-5"
```
## Usage Example
### Basic Chat
```go
provider := openai_compat.NewProvider(apiKey, apiBase, "")
messages := []providers.Message{
{Role: "system", Content: "You are a helpful assistant."},
{Role: "user", Content: "Hello!"},
}
response, err := provider.Chat(ctx, messages, nil, "gpt-4", map[string]interface{}{
"max_tokens": 1024,
"temperature": 0.7,
})
if err != nil {
return err
}
fmt.Println(response.Content)
```
### With Tool Calling
```go
tools := []providers.ToolDefinition{
{
Type: "function",
Function: providers.ToolFunctionDefinition{
Name: "get_weather",
Description: "Get current weather",
Parameters: map[string]interface{}{
"type": "object",
"properties": map[string]interface{}{
"location": map[string]interface{}{
"type": "string",
},
},
"required": []string{"location"},
},
},
},
}
response, err := provider.Chat(ctx, messages, tools, "gpt-4", options)
// Handle tool calls
for _, tc := range response.ToolCalls {
fmt.Printf("Tool: %s, Args: %v\n", tc.Name, tc.Arguments)
}
```
### With Fallback
```go
candidates := []providers.ModelCandidate{
{Provider: "openrouter", Model: "anthropic/claude-opus-4-5"},
{Provider: "openrouter", Model: "anthropic/claude-sonnet-4"},
{Provider: "groq", Model: "llama-3-70b"},
}
result, err := fallback.Execute(ctx, candidates,
func(ctx context.Context, provider, model string) (*providers.LLMResponse, error) {
return providerClient.Chat(ctx, messages, tools, model, options)
},
)
if err != nil {
return err
}
fmt.Printf("Succeeded with %s/%s\n", result.Provider, result.Model)
fmt.Println(result.Response.Content)
```
## Best Practices
1. **Always Use Context**: Pass context for cancellation
2. **Handle Timeouts**: Set appropriate timeouts
3. **Classify Errors**: Use FailoverError for fallback support
4. **Normalize Models**: Handle provider prefixes
5. **Validate Responses**: Check for empty or malformed responses
6. **Log Requests**: Log for debugging (with redacted API keys)
## See Also
- [Creating LLM Providers](../extending/creating-providers.md)
- [Provider Implementations](https://github.com/sipeed/picoclaw/tree/main/pkg/providers)
- [OpenAI-Compatible Provider](https://github.com/sipeed/picoclaw/tree/main/pkg/providers/openai_compat)

View file

@ -0,0 +1,520 @@
# Session Manager API Reference
This document provides detailed reference for the Session Manager API.
## Overview
The Session Manager handles conversation history storage and retrieval. It provides:
- In-memory caching for fast access
- Disk persistence for durability
- Automatic summarization support
- Thread-safe operations
## Types
### Session
Represents a conversation session.
```go
type Session struct {
Key string `json:"key"`
Messages []providers.Message `json:"messages"`
Summary string `json:"summary,omitempty"`
Created time.Time `json:"created"`
Updated time.Time `json:"updated"`
}
```
**Fields:**
| Field | Type | Description |
|-------|------|-------------|
| Key | string | Unique session identifier |
| Messages | []providers.Message | Conversation history |
| Summary | string | Summary of older messages |
| Created | time.Time | Session creation time |
| Updated | time.Time | Last update time |
### SessionManager
Manages sessions with caching and persistence.
```go
type SessionManager struct {
sessions map[string]*Session
mu sync.RWMutex
storage string
}
```
## Functions
### NewSessionManager
Creates a new session manager.
```go
func NewSessionManager(storage string) *SessionManager
```
**Parameters:**
- `storage`: Directory path for session files (empty for memory-only)
**Returns:** New SessionManager instance
```go
// With persistence
sm := session.NewSessionManager("/path/to/sessions")
// Memory-only
sm := session.NewSessionManager("")
```
## Methods
### GetOrCreate
Gets an existing session or creates a new one.
```go
func (sm *SessionManager) GetOrCreate(key string) *Session
```
**Parameters:**
- `key`: Session identifier
**Returns:** Session instance (existing or new)
```go
session := sm.GetOrCreate("telegram:123456")
```
### AddMessage
Adds a simple message to the session.
```go
func (sm *SessionManager) AddMessage(sessionKey, role, content string)
```
**Parameters:**
- `sessionKey`: Session identifier
- `role`: Message role ("user", "assistant", "system")
- `content`: Message content
```go
sm.AddMessage("telegram:123456", "user", "Hello!")
sm.AddMessage("telegram:123456", "assistant", "Hi there!")
```
### AddFullMessage
Adds a complete message with all fields.
```go
func (sm *SessionManager) AddFullMessage(sessionKey string, msg providers.Message)
```
**Parameters:**
- `sessionKey`: Session identifier
- `msg`: Complete message with tool calls, etc.
```go
sm.AddFullMessage("telegram:123456", providers.Message{
Role: "assistant",
Content: "Let me check that.",
ToolCalls: []providers.ToolCall{
{ID: "call_123", Name: "files_read", Arguments: map[string]interface{}{"path": "/tmp/file.txt"}},
},
})
```
### GetHistory
Gets the conversation history for a session.
```go
func (sm *SessionManager) GetHistory(key string) []providers.Message
```
**Parameters:**
- `key`: Session identifier
**Returns:** Copy of message history
```go
history := sm.GetHistory("telegram:123456")
for _, msg := range history {
fmt.Printf("%s: %s\n", msg.Role, msg.Content)
}
```
### SetHistory
Replaces the entire message history.
```go
func (sm *SessionManager) SetHistory(key string, history []providers.Message)
```
**Parameters:**
- `key`: Session identifier
- `history`: New message history
```go
newHistory := []providers.Message{
{Role: "system", Content: "You are helpful."},
{Role: "user", Content: "Hello"},
}
sm.SetHistory("telegram:123456", newHistory)
```
### GetSummary
Gets the session summary.
```go
func (sm *SessionManager) GetSummary(key string) string
```
**Parameters:**
- `key`: Session identifier
**Returns:** Summary string (empty if none)
```go
summary := sm.GetSummary("telegram:123456")
if summary != "" {
fmt.Println("Previous context:", summary)
}
```
### SetSummary
Sets the session summary.
```go
func (sm *SessionManager) SetSummary(key string, summary string)
```
**Parameters:**
- `key`: Session identifier
- `summary`: Summary text
```go
sm.SetSummary("telegram:123456", "User asked about weather. Discussed forecast for the week.")
```
### TruncateHistory
Truncates history to keep only the last N messages.
```go
func (sm *SessionManager) TruncateHistory(key string, keepLast int)
```
**Parameters:**
- `key`: Session identifier
- `keepLast`: Number of recent messages to keep (0 to clear all)
```go
// Keep only last 4 messages
sm.TruncateHistory("telegram:123456", 4)
// Clear all messages
sm.TruncateHistory("telegram:123456", 0)
```
### Save
Saves a session to disk.
```go
func (sm *SessionManager) Save(key string) error
```
**Parameters:**
- `key`: Session identifier
**Returns:** Error if save failed
**Note:** Only saves if storage path was configured.
```go
if err := sm.Save("telegram:123456"); err != nil {
log.Printf("Failed to save session: %v", err)
}
```
## Session Keys
Session keys uniquely identify conversations. Common formats:
| Format | Example | Description |
|--------|---------|-------------|
| channel:chatID | `telegram:123456` | Basic session |
| agent:agentID:channel:chatID | `agent:main:telegram:123456` | Agent-specific |
### Key Sanitization
Keys are sanitized for filesystem safety:
```go
// Colon (:) is replaced with underscore (_)
// "telegram:123456" -> file "telegram_123456.json"
```
## File Format
Sessions are stored as JSON files:
```json
{
"key": "telegram:123456",
"messages": [
{
"role": "user",
"content": "Hello!"
},
{
"role": "assistant",
"content": "Hi there!"
}
],
"summary": "",
"created": "2024-01-15T10:30:00Z",
"updated": "2024-01-15T10:31:00Z"
}
```
## Usage Patterns
### Basic Conversation
```go
sm := session.NewSessionManager(storagePath)
sessionKey := "telegram:123456"
// Get or create session
sess := sm.GetOrCreate(sessionKey)
// Add user message
sm.AddMessage(sessionKey, "user", "What's the weather?")
// ... LLM call ...
// Add assistant response
sm.AddMessage(sessionKey, "assistant", "It's sunny today.")
// Save
sm.Save(sessionKey)
```
### With Tool Calls
```go
// Add user message
sm.AddMessage(sessionKey, "user", "Read the config file")
// Add assistant message with tool call
sm.AddFullMessage(sessionKey, providers.Message{
Role: "assistant",
Content: "",
ToolCalls: []providers.ToolCall{{
ID: "call_1",
Name: "files_read",
Arguments: map[string]interface{}{"path": "config.json"},
}},
})
// Add tool result
sm.AddFullMessage(sessionKey, providers.Message{
Role: "tool",
Content: `{"setting": "value"}`,
ToolCallID: "call_1",
})
// Add final assistant response
sm.AddMessage(sessionKey, "assistant", "The config contains...")
```
### Summarization
```go
// Check if summarization needed
history := sm.GetHistory(sessionKey)
if len(history) > 20 {
// Generate summary
summary := generateSummary(history[:len(history)-4])
// Set summary
sm.SetSummary(sessionKey, summary)
// Keep only recent messages
sm.TruncateHistory(sessionKey, 4)
// Save
sm.Save(sessionKey)
}
```
### Building LLM Context
```go
func buildContext(sm *session.SessionManager, sessionKey, userMessage string) []providers.Message {
var messages []providers.Message
// System prompt
messages = append(messages, providers.Message{
Role: "system",
Content: "You are a helpful assistant.",
})
// Add summary if exists
if summary := sm.GetSummary(sessionKey); summary != "" {
messages = append(messages, providers.Message{
Role: "system",
Content: "Previous conversation summary: " + summary,
})
}
// Add history
messages = append(messages, sm.GetHistory(sessionKey)...)
// Add current message
messages = append(messages, providers.Message{
Role: "user",
Content: userMessage,
})
return messages
}
```
## Thread Safety
The SessionManager is thread-safe:
- All operations are protected by RWMutex
- Multiple goroutines can read simultaneously
- Write operations are exclusive
```go
// Safe to use from multiple goroutines
go func() {
sm.AddMessage("session1", "user", "Message 1")
}()
go func() {
sm.AddMessage("session2", "user", "Message 2")
}()
```
## Persistence
### Atomic Writes
Sessions are saved atomically:
1. Write to temporary file
2. Sync to disk
3. Rename to final location
This prevents corruption from crashes.
### Loading
Sessions are loaded lazily on `GetOrCreate`:
1. Check in-memory cache
2. If not found, load from disk
3. Cache in memory
### Storage Location
Typical storage locations:
```
~/.picoclaw/workspace/sessions/
├── telegram_123456.json
├── telegram_-1001234567890.json # Group chat
├── discord_123456789012345678.json
└── ...
```
## Error Handling
### Save Errors
```go
if err := sm.Save(sessionKey); err != nil {
if errors.Is(err, os.ErrInvalid) {
// Invalid session key
} else {
// Filesystem error
}
}
```
### Missing Sessions
```go
// GetHistory returns empty slice for missing sessions
history := sm.GetHistory("nonexistent")
// history == []providers.Message{}
// GetSummary returns empty string for missing sessions
summary := sm.GetSummary("nonexistent")
// summary == ""
```
## Best Practices
1. **Save After Changes**: Save after important operations
2. **Use Meaningful Keys**: Use consistent key formats
3. **Handle Errors**: Check for save errors
4. **Don't Block**: Save in goroutine if needed
5. **Summarize**: Keep history manageable with summaries
### Async Saving
```go
// Save without blocking
go func() {
if err := sm.Save(sessionKey); err != nil {
log.Printf("Failed to save session: %v", err)
}
}()
```
### Periodic Saving
```go
go func() {
ticker := time.NewTicker(30 * time.Second)
defer ticker.Stop()
for range ticker.C {
for _, key := range getActiveSessions() {
sm.Save(key)
}
}
}()
```
## Performance Characteristics
| Metric | Value |
|--------|-------|
| Memory | O(n) where n = total messages across sessions |
| Read | O(1) for cache hit, O(n) for file load |
| Write | O(1) for memory, O(n) for disk save |
| Thread Safety | Yes (RWMutex) |
## See Also
- [Data Flow](../data-flow.md)
- [Session Manager Implementation](https://github.com/sipeed/picoclaw/tree/main/pkg/session)
- [Provider Types](https://github.com/sipeed/picoclaw/tree/main/pkg/providers/protocoltypes)

View file

@ -0,0 +1,469 @@
# Tool Interface Reference
This document provides detailed reference for the Tool interface and related types.
## Core Interface
### Tool
The base interface that all tools must implement.
```go
type Tool interface {
Name() string
Description() string
Parameters() map[string]interface{}
Execute(ctx context.Context, args map[string]interface{}) *ToolResult
}
```
#### Methods
##### Name() string
Returns the unique identifier for the tool.
- **Returns**: Tool name (e.g., "files_read", "exec", "message")
- **Usage**: Used for tool lookup and LLM function calling
```go
func (t *MyTool) Name() string {
return "my-tool"
}
```
##### Description() string
Returns a human-readable description of what the tool does.
- **Returns**: Description text
- **Usage**: Helps the LLM understand when to use this tool
```go
func (t *MyTool) Description() string {
return "Performs a specific action. Use this when you need to..."
}
```
##### Parameters() map[string]interface{}
Returns the JSON Schema for the tool's parameters.
- **Returns**: JSON Schema object
- **Usage**: Defines the structure of arguments for LLM function calling
```go
func (t *MyTool) Parameters() map[string]interface{} {
return map[string]interface{}{
"type": "object",
"properties": map[string]interface{}{
"path": map[string]interface{}{
"type": "string",
"description": "File path to read",
},
"encoding": map[string]interface{}{
"type": "string",
"default": "utf-8",
"description": "File encoding",
},
},
"required": []string{"path"},
}
}
```
##### Execute(ctx context.Context, args map[string]interface{}) *ToolResult
Executes the tool with the provided arguments.
- **Parameters**:
- `ctx`: Context for cancellation and timeout
- `args`: Arguments matching the Parameters schema
- **Returns**: ToolResult with execution outcome
```go
func (t *MyTool) Execute(ctx context.Context, args map[string]interface{}) *ToolResult {
path, ok := args["path"].(string)
if !ok {
return ErrorResult("path is required")
}
// Do work...
content, err := os.ReadFile(path)
if err != nil {
return ErrorResult(fmt.Sprintf("failed to read: %v", err))
}
return UserResult(string(content))
}
```
## Optional Interfaces
### ContextualTool
For tools that need channel/chat context.
```go
type ContextualTool interface {
Tool
SetContext(channel, chatID string)
}
```
#### SetContext(channel, chatID string)
Called before Execute to provide message context.
- **Parameters**:
- `channel`: Platform identifier (e.g., "telegram")
- `chatID`: Chat/conversation identifier
```go
type MessageTool struct {
defaultChannel string
defaultChatID string
}
func (t *MessageTool) SetContext(channel, chatID string) {
t.defaultChannel = channel
t.defaultChatID = chatID
}
```
### AsyncTool
For tools that execute asynchronously.
```go
type AsyncCallback func(ctx context.Context, result *ToolResult)
type AsyncTool interface {
Tool
SetCallback(cb AsyncCallback)
}
```
#### SetCallback(cb AsyncCallback)
Registers a callback for async completion notification.
- **Parameters**:
- `cb`: Callback function to invoke when complete
```go
type SpawnTool struct {
callback AsyncCallback
}
func (t *SpawnTool) SetCallback(cb AsyncCallback) {
t.callback = cb
}
func (t *SpawnTool) Execute(ctx context.Context, args map[string]interface{}) *ToolResult {
go func() {
// Do async work
result := doWork(args)
// Notify completion
if t.callback != nil {
t.callback(ctx, result)
}
}()
return AsyncResult("Task started")
}
```
## ToolResult
The return type for tool execution.
```go
type ToolResult struct {
ForLLM string `json:"for_llm"`
ForUser string `json:"for_user,omitempty"`
Silent bool `json:"silent"`
IsError bool `json:"is_error"`
Async bool `json:"async"`
Err error `json:"-"`
}
```
### Fields
| Field | Type | Description |
|-------|------|-------------|
| ForLLM | string | Content sent to LLM (always required) |
| ForUser | string | Content sent directly to user |
| Silent | bool | If true, no message sent to user |
| IsError | bool | Indicates execution failure |
| Async | bool | Indicates async operation |
| Err | error | Underlying error (not JSON serialized) |
### Constructor Functions
#### NewToolResult(forLLM string) *ToolResult
Creates a basic result with LLM content.
```go
result := NewToolResult("Operation completed")
```
#### SilentResult(forLLM string) *ToolResult
Creates a silent result (no user message).
```go
result := SilentResult("File saved")
```
#### UserResult(content string) *ToolResult
Creates a result with same content for LLM and user.
```go
result := UserResult("Found 42 items")
```
#### ErrorResult(message string) *ToolResult
Creates an error result.
```go
result := ErrorResult("Failed to process: reason")
```
#### AsyncResult(forLLM string) *ToolResult
Creates an async result for background operations.
```go
result := AsyncResult("Task started, will notify on completion")
```
### Methods
#### WithError(err error) *ToolResult
Attaches an underlying error for logging.
```go
result := ErrorResult("Failed").WithError(err)
```
## ToolRegistry
Manages registered tools.
```go
type ToolRegistry struct {
tools map[string]Tool
mu sync.RWMutex
}
```
### Methods
#### NewToolRegistry() *ToolRegistry
Creates a new empty registry.
```go
registry := tools.NewToolRegistry()
```
#### Register(tool Tool)
Registers a tool.
```go
registry.Register(tools.NewMessageTool())
```
#### Get(name string) (Tool, bool)
Retrieves a tool by name.
```go
tool, ok := registry.Get("message")
```
#### Execute(ctx context.Context, name string, args map[string]interface{}) *ToolResult
Executes a tool by name.
```go
result := registry.Execute(ctx, "message", map[string]interface{}{
"content": "Hello",
})
```
#### ExecuteWithContext(ctx context.Context, name string, args map[string]interface{}, channel, chatID string, asyncCallback AsyncCallback) *ToolResult
Executes with context and optional async callback.
```go
result := registry.ExecuteWithContext(ctx, "spawn", args, "telegram", "123", callback)
```
#### GetDefinitions() []map[string]interface{}
Returns all tool definitions in JSON Schema format.
```go
defs := registry.GetDefinitions()
```
#### ToProviderDefs() []providers.ToolDefinition
Returns definitions in provider-compatible format.
```go
providerDefs := registry.ToProviderDefs()
```
#### List() []string
Returns all registered tool names.
```go
names := registry.List() // ["message", "exec", "files_read", ...]
```
#### Count() int
Returns the number of registered tools.
```go
count := registry.Count()
```
#### GetSummaries() []string
Returns human-readable summaries.
```go
summaries := registry.GetSummaries()
// ["- `message` - Send a message to user", ...]
```
## Helper Functions
### ToolToSchema(tool Tool) map[string]interface{}
Converts a tool to JSON Schema format.
```go
schema := tools.ToolToSchema(myTool)
// {
// "type": "function",
// "function": {
// "name": "my-tool",
// "description": "...",
// "parameters": {...}
// }
// }
```
## Parameter Schema Guide
### Basic Types
```go
// String
"name": map[string]interface{}{
"type": "string",
"description": "User name",
}
// Integer
"count": map[string]interface{}{
"type": "integer",
"description": "Number of items",
"minimum": 1,
"maximum": 100,
}
// Number (float)
"ratio": map[string]interface{}{
"type": "number",
"description": "Ratio value",
"minimum": 0.0,
"maximum": 1.0,
}
// Boolean
"enabled": map[string]interface{}{
"type": "boolean",
"description": "Enable feature",
"default": false,
}
```
### Enumerations
```go
"mode": map[string]interface{}{
"type": "string",
"enum": []string{"fast", "normal", "thorough"},
"description": "Processing mode",
}
```
### Arrays
```go
"tags": map[string]interface{}{
"type": "array",
"items": map[string]interface{}{"type": "string"},
"description": "List of tags",
}
```
### Nested Objects
```go
"options": map[string]interface{}{
"type": "object",
"properties": map[string]interface{}{
"timeout": map[string]interface{}{
"type": "integer",
"description": "Timeout in seconds",
},
"retries": map[string]interface{}{
"type": "integer",
"description": "Number of retries",
},
},
}
```
### Required Fields
```go
map[string]interface{}{
"type": "object",
"properties": map[string]interface{}{
"path": map[string]interface{}{...},
"mode": map[string]interface{}{...},
},
"required": []string{"path"}, // mode is optional
}
```
## Best Practices
1. **Clear Names**: Use lowercase with underscores
2. **Good Descriptions**: Explain when and how to use the tool
3. **Validate Inputs**: Check all arguments before processing
4. **Meaningful Errors**: Provide actionable error messages
5. **Use Context**: Support cancellation via context
6. **Choose Right Result Type**: Match result type to use case
7. **Handle Panics**: Recover in Execute to prevent crashes
## See Also
- [Creating Custom Tools](../extending/creating-tools.md)
- [Tool Implementations](https://github.com/sipeed/picoclaw/tree/main/pkg/tools)

View file

@ -0,0 +1,354 @@
# System Architecture
This document provides an overview of PicoClaw's system architecture, including its core components and how they interact.
## High-Level Architecture
PicoClaw follows a **message bus architecture** pattern where components communicate asynchronously through a central message bus. This design enables loose coupling between components and makes it easy to add new channels or modify processing logic.
```
┌─────────────────────────────────────────────────────────────────┐
│ External Platforms │
│ Telegram Discord Slack WhatsApp CLI etc. │
└───────┬───────────┬─────────┬─────────┬─────────┬───────────────┘
│ │ │ │ │
▼ ▼ ▼ ▼ ▼
┌─────────────────────────────────────────────────────────────────┐
│ Channel Layer │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │Telegram │ │ Discord │ │ Slack │ │ CLI │ ... │
│ │Channel │ │ Channel │ │ Channel │ │ Channel │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
└───────┼────────────┼────────────┼────────────┼──────────────────┘
│ │ │ │
▼ ▼ ▼ ▼
┌─────────────────────────────────────────────────────────────────┐
│ Message Bus │
│ ┌─────────────────────┐ ┌─────────────────────┐ │
│ │ Inbound Channel │ │ Outbound Channel │ │
│ │ (buffer: 100) │ │ (buffer: 100) │ │
│ └──────────┬──────────┘ └──────────┬──────────┘ │
└─────────────┼──────────────────────────┼────────────────────────┘
│ ▲
▼ │
┌─────────────────────────────────────────────────────────────────┐
│ Agent Layer │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ AgentLoop │ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ Router │→ │ Agent │→ │ LLM │ │ │
│ │ │ │ │ Registry │ │ Provider │ │ │
│ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ ┌─────────────┐ │ │
│ │ │ Tools │ │ │
│ │ │ Registry │ │ │
│ │ └─────────────┘ │ │
│ └─────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ Storage Layer │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Sessions │ │ Memory │ │ Cron │ │
│ │ Manager │ │ (MD) │ │ Jobs │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────────────┘
```
## Core Components
### 1. Message Bus (`pkg/bus/`)
The message bus is the central communication hub. It provides:
- **Inbound messages**: Messages from external platforms
- **Outbound messages**: Responses to be sent to platforms
- **Handler registration**: Maps channel names to handlers
```go
type MessageBus struct {
inbound chan InboundMessage
outbound chan OutboundMessage
handlers map[string]MessageHandler
}
```
Key features:
- Buffered channels (capacity: 100) for async processing
- Thread-safe operations with mutex protection
- Context-aware consumption for graceful shutdown
### 2. Agent Loop (`pkg/agent/loop.go`)
The AgentLoop is the core message processing engine:
```go
type AgentLoop struct {
bus *bus.MessageBus
cfg *config.Config
registry *AgentRegistry
state *state.Manager
fallback *providers.FallbackChain
channelManager *channels.Manager
}
```
Responsibilities:
- Consumes messages from the inbound bus
- Routes messages to appropriate agents
- Builds context with history and system prompts
- Calls LLM providers with fallback support
- Executes tool calls from LLM responses
- Publishes responses to the outbound bus
### 3. Agent Registry (`pkg/agent/registry.go`)
Manages multiple agents with different configurations:
```go
type AgentRegistry struct {
agents map[string]*AgentInstance
default string
routes []routing.Rule
}
```
Features:
- Multi-agent support with isolated workspaces
- Message routing based on channel, peer type, etc.
- Agent-specific tool configurations
### 4. Agent Instance (`pkg/agent/instance.go`)
Represents a single agent configuration:
```go
type AgentInstance struct {
ID string
Model string
Candidates []providers.ModelCandidate
Workspace string
Tools *tools.ToolRegistry
Sessions *session.SessionManager
ContextBuilder *ContextBuilder
MaxIterations int
ContextWindow int
}
```
### 5. Channels (`pkg/channels/`)
Channels handle communication with external platforms:
```go
type Channel interface {
Name() string
Start(ctx context.Context) error
Stop(ctx context.Context) error
Send(ctx context.Context, msg bus.OutboundMessage) error
IsRunning() bool
IsAllowed(senderID string) bool
}
```
Built-in channels:
- Telegram
- Discord
- Slack
- WhatsApp
- LINE
- QQ (OneBot)
- DingTalk
- Feishu/Lark
- MaixCam
### 6. LLM Providers (`pkg/providers/`)
Providers implement the LLM API integration:
```go
type LLMProvider interface {
Chat(ctx context.Context, messages []Message, tools []ToolDefinition,
model string, options map[string]interface{}) (*LLMResponse, error)
GetDefaultModel() string
}
```
Built-in providers:
- OpenAI-compatible (OpenRouter, Groq, etc.)
- Anthropic/Claude
- Claude CLI
- Codex CLI
- GitHub Copilot
### 7. Tools (`pkg/tools/`)
Tools enable the agent to interact with the world:
```go
type Tool interface {
Name() string
Description() string
Parameters() map[string]interface{}
Execute(ctx context.Context, args map[string]interface{}) *ToolResult
}
```
Built-in tools:
- `files_read` / `files_write` / `files_list` - File operations
- `exec` - Shell command execution
- `web_search` / `web_fetch` - Web operations
- `message` - Send messages to users
- `spawn` - Spawn subagents
- `cron` - Schedule tasks
- `i2c` / `spi` - Hardware interfaces (Linux only)
### 8. Session Manager (`pkg/session/manager.go`)
Manages conversation history:
```go
type SessionManager struct {
sessions map[string]*Session
mu sync.RWMutex
storage string
}
type Session struct {
Key string
Messages []providers.Message
Summary string
Created time.Time
Updated time.Time
}
```
Features:
- In-memory caching with disk persistence
- Automatic summarization when history exceeds thresholds
- Thread-safe operations
### 9. Skills Loader (`pkg/skills/loader.go`)
Loads custom skills from markdown files:
```go
type SkillsLoader struct {
workspace string
workspaceSkills string
globalSkills string
builtinSkills string
}
```
Skills are loaded from three locations (in priority order):
1. Workspace skills (project-level)
2. Global skills (`~/.picoclaw/skills`)
3. Built-in skills
## Data Flow
See [Data Flow](data-flow.md) for a detailed explanation of how messages flow through the system.
## Configuration
Configuration is loaded from `~/.picoclaw/config.json`:
```json
{
"providers": {
"openrouter": {
"api_key": "sk-or-..."
}
},
"agents": {
"defaults": {
"model": "openrouter/anthropic/claude-opus-4-5"
},
"list": [
{
"id": "main",
"workspace": "~/.picoclaw/workspace"
}
]
}
}
```
## Multi-Agent Support
PicoClaw supports multiple agents with isolated configurations:
1. **Agent Definition**: Each agent has a unique ID and workspace
2. **Routing**: Messages are routed based on rules (channel, peer type, etc.)
3. **Isolation**: Each agent has its own sessions, tools, and configuration
See [Multi-Agent Guide](../user-guide/advanced/multi-agent.md) for details.
## Security Sandbox
When `restrict_to_workspace: true` (default):
- File operations are limited to the workspace directory
- Shell commands must execute within workspace
- Dangerous commands are always blocked (`rm -rf`, `format`, `dd`, `shutdown`)
See [Security Sandbox](../user-guide/advanced/security-sandbox.md) for details.
## Workspace Structure
```
~/.picoclaw/workspace/
├── sessions/ # Conversation history
├── memory/ # Long-term memory (MEMORY.md)
├── cron/ # Scheduled jobs
├── skills/ # Custom skills
├── AGENT.md # Agent behavior guide
├── IDENTITY.md # Agent identity
└── HEARTBEAT.md # Periodic task prompts
```
## Key Design Patterns
### 1. Interface-Based Design
Core components are defined as interfaces, making it easy to:
- Add new LLM providers
- Create custom tools
- Implement new channels
### 2. Dependency Injection
Components receive dependencies through constructors:
```go
func NewAgentLoop(cfg *config.Config, msgBus *bus.MessageBus,
provider providers.LLMProvider) *AgentLoop
```
### 3. Context Propagation
All long-running operations accept `context.Context` for:
- Cancellation signals
- Timeout handling
- Request-scoped values
### 4. Error Wrapping
Errors are wrapped with context:
```go
return fmt.Errorf("failed to process message: %w", err)
```
### 5. Structured Logging
Logging uses structured fields:
```go
logger.InfoCF("agent", "Processing message",
map[string]interface{}{
"channel": msg.Channel,
"chat_id": msg.ChatID,
})
```

View file

@ -0,0 +1,266 @@
# Building from Source
This guide explains how to build PicoClaw from source code.
## Prerequisites
### Go
PicoClaw requires Go 1.21 or later. Check your Go version:
```bash
go version
```
If Go is not installed, download it from [golang.org](https://golang.org/dl/).
### Make
PicoClaw uses a Makefile for build automation. Ensure `make` is installed:
```bash
make --version
```
### Git
For cloning the repository:
```bash
git --version
```
## Getting the Source Code
Clone the repository:
```bash
git clone https://github.com/sipeed/picoclaw.git
cd picoclaw
```
## Dependencies
Download dependencies:
```bash
make deps
```
This runs `go mod download` to fetch all required modules.
## Building
### Build for Current Platform
Build for your current operating system and architecture:
```bash
make build
```
This will:
1. Run `go generate` to generate any required code
2. Build the binary to `build/picoclaw`
The output binary will be at `build/picoclaw` (or `build/picoclaw.exe` on Windows).
### Build for All Platforms
Build for all supported platforms:
```bash
make build-all
```
This creates binaries for:
- `linux-amd64`
- `linux-arm64`
- `linux-loong64`
- `linux-riscv64`
- `darwin-arm64` (macOS Apple Silicon)
- `windows-amd64`
Binaries are placed in the `build/` directory with platform-specific naming.
### Manual Build
You can also build manually with Go commands:
```bash
# Generate code (if needed)
go generate ./...
# Build for current platform
go build -o build/picoclaw ./cmd/picoclaw
# Build with optimizations
go build -ldflags="-s -w" -o build/picoclaw ./cmd/picoclaw
```
### Cross-Compilation
Build for a specific platform:
```bash
# Linux AMD64
GOOS=linux GOARCH=amd64 go build -o build/picoclaw-linux-amd64 ./cmd/picoclaw
# Linux ARM64 (Raspberry Pi, etc.)
GOOS=linux GOARCH=arm64 go build -o build/picoclaw-linux-arm64 ./cmd/picoclaw
# macOS ARM64 (Apple Silicon)
GOOS=darwin GOARCH=arm64 go build -o build/picoclaw-darwin-arm64 ./cmd/picoclaw
# Windows AMD64
GOOS=windows GOARCH=amd64 go build -o build/picoclaw-windows-amd64.exe ./cmd/picoclaw
```
## Installation
### Install to Default Location
Install to `~/.local/bin`:
```bash
make install
```
Ensure `~/.local/bin` is in your PATH:
```bash
export PATH="$HOME/.local/bin:$PATH"
```
Add to your shell profile for persistence:
```bash
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
# or
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc
```
### Custom Installation
Install to a custom location:
```bash
go build -o /usr/local/bin/picoclaw ./cmd/picoclaw
```
## Verification
Verify the build:
```bash
./build/picoclaw --version
```
Run a quick test:
```bash
# Interactive mode
./build/picoclaw agent
# Single message
./build/picoclaw agent -m "Hello, PicoClaw!"
```
## Development Build
For development, you may want to build with debug symbols:
```bash
go build -gcflags="all=-N -l" -o build/picoclaw-debug ./cmd/picoclaw
```
## Build Options
### Makefile Targets
| Target | Description |
|--------|-------------|
| `deps` | Download dependencies |
| `build` | Build for current platform |
| `build-all` | Build for all platforms |
| `install` | Install to ~/.local/bin |
| `test` | Run tests |
| `vet` | Run linter |
| `fmt` | Format code |
| `check` | Run all checks (deps, fmt, vet, test) |
| `clean` | Remove build artifacts |
### Environment Variables
| Variable | Description |
|----------|-------------|
| `GOOS` | Target operating system |
| `GOARCH` | Target architecture |
| `CGO_ENABLED` | Enable CGO (default: 0) |
## Troubleshooting
### "go: command not found"
Install Go from [golang.org](https://golang.org/dl/).
### "go: cannot find main module"
Ensure you're in the project root directory:
```bash
cd picoclaw
```
### Build Errors
1. Clean and rebuild:
```bash
go clean -cache
make build
```
2. Update dependencies:
```bash
go mod tidy
make deps
```
3. Check Go version:
```bash
go version # Should be 1.21+
```
### Hardware Tool Build Errors
I2C and SPI tools require Linux-specific system calls. On non-Linux platforms, these tools return errors at runtime but the build should succeed.
If you see build errors related to these tools:
```bash
# The build should still work - these are stub implementations
make build
```
## Docker Build (Optional)
Build with Docker:
```bash
# Build image
docker build -t picoclaw .
# Run container
docker run -it picoclaw agent -m "Hello"
```
## Next Steps
After building:
1. [Configure PicoClaw](../getting-started/configuration-basics.md)
2. [Run your first chat](../getting-started/first-chat.md)
3. [Set up channels](../user-guide/channels/README.md)

View file

@ -0,0 +1,492 @@
# Code Style Guide
This document describes the code style conventions used in PicoClaw.
## Overview
PicoClaw follows standard Go conventions with some project-specific guidelines. When in doubt, refer to:
- [Effective Go](https://golang.org/doc/effective_go)
- [Go Code Review Comments](https://github.com/golang/go/wiki/CodeReviewComments)
## Formatting
### Automatic Formatting
Use `gofmt` or `go fmt`:
```bash
# Format all code
make fmt
# Or manually
go fmt ./pkg/...
```
### General Rules
- Use tabs for indentation (Go standard)
- No trailing whitespace
- Files end with a newline
## Naming Conventions
### Packages
- Short, lowercase names
- No underscores or mixedCaps
- Single word preferred
```go
// Good
package agent
package tools
package bus
// Bad
package agentLoop
package tool_registry
```
### Types
- Exported types: PascalCase
- Private types: camelCase
- Interface names: typically end with "er" for single-method interfaces
```go
// Good
type Tool interface { ... }
type LLMProvider interface { ... }
type toolRegistry struct { ... }
// Bad
type tool_interface interface { ... }
type ToolRegistry struct { ... } // if private
```
### Functions and Methods
- Exported: PascalCase
- Private: camelCase
- Constructors: `NewTypeName()`
```go
// Good
func NewToolRegistry() *ToolRegistry
func (r *ToolRegistry) Register(tool Tool)
func (r *toolRegistry) getTool(name string) Tool
// Bad
func new_ToolRegistry() *ToolRegistry
func (r *ToolRegistry) register_tool(tool Tool)
```
### Variables
- Short names for short scope
- Descriptive names for longer scope
- camelCase for local variables
```go
// Good - short scope
for i, msg := range messages {
fmt.Println(i, msg)
}
// Good - longer scope
sessionManager := session.NewManager(storage)
// Bad
messageIndex := 0 // too long for short scope
```
### Constants
- camelCase or PascalCase depending on export
```go
const (
maxIterations = 10
DefaultModel = "gpt-4"
)
```
## Error Handling
### Error Wrapping
Use `fmt.Errorf` with `%w` for wrapping:
```go
// Good
if err != nil {
return fmt.Errorf("failed to process message: %w", err)
}
// Bad
if err != nil {
return fmt.Errorf("failed to process message: %v", err)
}
```
### Error Returns
Return errors, don't panic:
```go
// Good
func (t *Tool) Execute(ctx context.Context, args map[string]interface{}) (*ToolResult, error) {
if err := validate(args); err != nil {
return nil, fmt.Errorf("validation failed: %w", err)
}
// ...
}
// Bad
func (t *Tool) Execute(ctx context.Context, args map[string]interface{}) *ToolResult {
if err := validate(args); err != nil {
panic(err) // Don't panic in library code
}
// ...
}
```
### Custom Errors
Define custom error types when appropriate:
```go
type FailoverError struct {
Reason FailoverReason
Provider string
Model string
Status int
Wrapped error
}
func (e *FailoverError) Error() string {
return fmt.Sprintf("failover(%s): provider=%s model=%s status=%d: %v",
e.Reason, e.Provider, e.Model, e.Status, e.Wrapped)
}
func (e *FailoverError) Unwrap() error {
return e.Wrapped
}
```
## Logging
### Structured Logging
Use the project's logger package:
```go
// Good
logger.InfoCF("agent", "Processing message",
map[string]interface{}{
"channel": msg.Channel,
"chat_id": msg.ChatID,
"sender": msg.SenderID,
})
logger.ErrorCF("tool", "Tool execution failed",
map[string]interface{}{
"tool": name,
"error": err.Error(),
})
// Bad
log.Printf("Processing message from %s", msg.Channel)
```
### Log Levels
- `DebugCF`: Detailed information for debugging
- `InfoCF`: General operational information
- `WarnCF`: Warning conditions
- `ErrorCF`: Error conditions
### Component Names
Use consistent component names:
- `"agent"` - Agent loop operations
- `"tool"` - Tool execution
- `"channel"` - Channel operations
- `"provider"` - LLM provider operations
- `"session"` - Session management
## Comments
### Package Comments
Document packages with a package comment:
```go
// Package agent provides the core agent loop for processing messages.
// It handles message routing, LLM interaction, and tool execution.
package agent
```
### Function Comments
Document exported functions:
```go
// Execute processes the tool call with the given arguments.
// It returns a ToolResult containing the output for both the LLM and user.
//
// The args map must contain the parameters defined by Parameters().
// If a required parameter is missing, an error result is returned.
func (t *MessageTool) Execute(ctx context.Context, args map[string]interface{}) *ToolResult {
```
### Inline Comments
Use sparingly and only when necessary:
```go
// Check for async tools and inject callback if needed
if asyncTool, ok := tool.(AsyncTool); ok && asyncCallback != nil {
asyncTool.SetCallback(asyncCallback)
}
```
### TODO Comments
```go
// TODO(username): Add support for streaming responses
// TODO: Consider caching provider responses
```
## Code Organization
### File Organization
Order within a file:
1. Package declaration
2. Imports
3. Constants
4. Variables
5. Types
6. Functions (exported first, then private)
### Import Organization
Group imports:
```go
import (
// Standard library
"context"
"fmt"
// External packages
"github.com/something/external"
// Internal packages
"github.com/sipeed/picoclaw/pkg/tools"
)
```
### Function Length
Keep functions focused and reasonably sized:
- Single responsibility
- Break up long functions
- Extract helper functions when needed
## Interfaces
### Define Interfaces Where Used
Define interfaces in the package that uses them:
```go
// In pkg/agent/loop.go
type LLMProvider interface {
Chat(ctx context.Context, messages []providers.Message, ...) (*LLMResponse, error)
}
```
### Small Interfaces
Prefer small, focused interfaces:
```go
// Good
type Tool interface {
Name() string
Description() string
Parameters() map[string]interface{}
Execute(ctx context.Context, args map[string]interface{}) *ToolResult
}
type ContextualTool interface {
Tool
SetContext(channel, chatID string)
}
// Bad - too large
type MegaInterface interface {
Name() string
Description() string
Parameters() map[string]interface{}
Execute(ctx context.Context, args map[string]interface{}) *ToolResult
SetContext(channel, chatID string)
SetCallback(cb AsyncCallback)
Start() error
Stop() error
}
```
## Testing
### Test File Naming
- Test files: `*_test.go`
- Integration tests: `*_integration_test.go`
### Test Function Naming
```go
func TestFunctionName(t *testing.T) {}
func TestFunctionName_Scenario(t *testing.T) {}
func TestType_Method(t *testing.T) {}
```
### Table-Driven Tests
```go
func TestValidateInput(t *testing.T) {
tests := []struct {
name string
input string
wantErr bool
}{
{"valid", "hello", false},
{"empty", "", true},
{"whitespace", " ", true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := validateInput(tt.input)
if (err != nil) != tt.wantErr {
t.Errorf("validateInput() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
```
## Concurrency
### Context for Cancellation
Always accept context:
```go
func (p *Provider) Chat(ctx context.Context, messages []Message, ...) (*Response, error) {
req, _ := http.NewRequestWithContext(ctx, "POST", url, body)
// ...
}
```
### Goroutine Safety
Document thread-safety:
```go
// ToolRegistry is safe for concurrent use.
type ToolRegistry struct {
tools map[string]Tool
mu sync.RWMutex
}
```
### Wait for Goroutines
```go
var wg sync.WaitGroup
for _, item := range items {
wg.Add(1)
go func(i Item) {
defer wg.Done()
process(i)
}
wg.Wait()
```
## JSON Configuration
### Field Tags
Use snake_case for JSON field names:
```go
type Config struct {
APIKey string `json:"api_key"`
MaxRetries int `json:"max_retries"`
ModelName string `json:"model_name"`
}
```
## Avoid These Patterns
### Global Variables
Avoid global state; use dependency injection:
```go
// Bad
var globalConfig *Config
func Process() {
apiKey := globalConfig.APIKey
}
// Good
type Processor struct {
config *Config
}
func NewProcessor(config *Config) *Processor {
return &Processor{config: config}
}
func (p *Processor) Process() {
apiKey := p.config.APIKey
}
```
### Interface Pollution
Don't define interfaces prematurely:
```go
// Bad - interface for single implementation
type StringProcessor interface {
Process(s string) string
}
type UpperCaseProcessor struct{}
// Good - define interface when you have multiple implementations
// or when mocking for tests
```
## Summary
1. Run `make fmt` before committing
2. Follow standard Go conventions
3. Use structured logging
4. Wrap errors with context
5. Write tests for new code
6. Document exported functions
7. Keep interfaces small
For questions about style not covered here, refer to [Effective Go](https://golang.org/doc/effective_go).

View file

@ -0,0 +1,361 @@
# Contribution Guidelines
Thank you for your interest in contributing to PicoClaw! This document provides guidelines and instructions for contributing.
## Table of Contents
- [Code of Conduct](#code-of-conduct)
- [Getting Started](#getting-started)
- [Development Workflow](#development-workflow)
- [Pull Request Process](#pull-request-process)
- [Coding Standards](#coding-standards)
- [Commit Guidelines](#commit-guidelines)
- [Reporting Issues](#reporting-issues)
- [Feature Requests](#feature-requests)
## Code of Conduct
Be respectful and inclusive. We welcome contributions from everyone. Please be constructive in discussions and reviews.
## Getting Started
### 1. Fork and Clone
```bash
# Fork the repository on GitHub, then clone your fork
git clone https://github.com/YOUR_USERNAME/picoclaw.git
cd picoclaw
# Add upstream remote
git remote add upstream https://github.com/sipeed/picoclaw.git
```
### 2. Set Up Development Environment
```bash
# Install dependencies
make deps
# Build
make build
# Run tests
make test
```
### 3. Create a Branch
```bash
# Update main branch
git checkout main
git pull upstream main
# Create feature branch
git checkout -b feature/my-feature
```
## Development Workflow
### Make Changes
1. Make your changes in your feature branch
2. Add or update tests as needed
3. Update documentation if applicable
### Run Checks
Before submitting, run all checks:
```bash
make check
```
This runs:
- `make deps` - Download dependencies
- `make fmt` - Format code
- `make vet` - Run linter
- `make test` - Run tests
### Run Specific Tests
```bash
# Test a specific package
go test ./pkg/tools/... -v
# Run a specific test
go test ./pkg/tools/... -v -run TestMessageTool
```
## Pull Request Process
### 1. Push Changes
```bash
git push origin feature/my-feature
```
### 2. Create Pull Request
1. Go to your fork on GitHub
2. Click "Pull Request"
3. Select your feature branch
4. Fill in the PR template
### 3. PR Requirements
- [ ] All tests pass
- [ ] Code is formatted (`make fmt`)
- [ ] Linter passes (`make vet`)
- [ ] Documentation updated (if applicable)
- [ ] PR description explains the change
- [ ] Commits follow [commit guidelines](#commit-guidelines)
### 4. Code Review
- Respond to review feedback promptly
- Make requested changes in new commits
- Mark conversations as resolved
### 5. Merge
PRs are merged by maintainers after approval.
## Coding Standards
### Go Style
Follow standard Go conventions:
```bash
# Format code
make fmt
# Or manually
go fmt ./pkg/...
```
### Error Handling
Wrap errors with context:
```go
// Good
if err != nil {
return fmt.Errorf("failed to process message: %w", err)
}
// Bad
if err != nil {
return err
}
```
### Logging
Use structured logging:
```go
// Good
logger.InfoCF("agent", "Processing message",
map[string]interface{}{
"channel": msg.Channel,
"chat_id": msg.ChatID,
})
// Bad
log.Printf("Processing message from %s", msg.Channel)
```
### Comments
- Write self-documenting code
- Add comments for exported functions
- Document complex logic
```go
// Execute processes the tool call with the given arguments.
// It returns a ToolResult containing the output for both the LLM and user.
func (t *MessageTool) Execute(ctx context.Context, args map[string]interface{}) *ToolResult {
// Implementation...
}
```
### Interfaces
Use interfaces for extensibility:
```go
// Good - interface for extension
type Tool interface {
Name() string
Description() string
Parameters() map[string]interface{}
Execute(ctx context.Context, args map[string]interface{}) *ToolResult
}
// Bad - concrete type only
type MessageTool struct { ... }
```
### Context
Always accept context for long-running operations:
```go
// Good
func (p *Provider) Chat(ctx context.Context, ...) (*Response, error)
// Bad
func (p *Provider) Chat(...) (*Response, error)
```
## Commit Guidelines
### Commit Message Format
```
<type>: <subject>
[optional body]
[optional footer]
```
### Types
- `feat`: New feature
- `fix`: Bug fix
- `docs`: Documentation only
- `style`: Formatting, no code change
- `refactor`: Code restructuring
- `test`: Adding/updating tests
- `chore`: Maintenance tasks
### Examples
```
feat: add support for Slack channel
Add Slack channel integration using the Slack API.
Supports both public channels and direct messages.
Closes #123
```
```
fix: handle empty message content in agent loop
The agent loop was crashing when receiving empty messages.
Added validation to skip processing empty content.
```
```
docs: update installation instructions for Windows
```
### Keep Commits Atomic
- One logical change per commit
- Each commit should be able to stand alone
- Don't mix unrelated changes
## Reporting Issues
### Bug Reports
Include:
1. **Description**: Clear description of the bug
2. **Steps to Reproduce**: How to trigger the bug
3. **Expected Behavior**: What you expected to happen
4. **Actual Behavior**: What actually happened
5. **Environment**:
- OS and version
- Go version
- PicoClaw version
6. **Logs**: Relevant log output (use `--debug`)
### Issue Template
```markdown
## Description
[Describe the bug]
## Steps to Reproduce
1. [First step]
2. [Second step]
3. [Third step]
## Expected Behavior
[What should happen]
## Actual Behavior
[What actually happens]
## Environment
- OS: [e.g., macOS 14.0]
- Go version: [e.g., 1.21]
- PicoClaw version: [e.g., v0.1.0]
## Logs
```
[paste relevant logs]
```
```
## Feature Requests
Include:
1. **Problem**: What problem does this solve?
2. **Solution**: Describe your proposed solution
3. **Alternatives**: Other solutions you considered
4. **Use Case**: How would this be used?
## Project Structure
When adding new features, place them in appropriate directories:
```
pkg/
├── agent/ # Core agent logic
├── bus/ # Message bus
├── channels/ # Platform integrations
│ └── slack.go # Add new channels here
├── providers/ # LLM providers
│ └── myprovider/
│ └── provider.go # Add new providers here
├── tools/ # Tool implementations
│ └── mytool.go # Add new tools here
└── skills/ # Skill loading
```
## Documentation
Update documentation for:
- New features
- Changed behavior
- New configuration options
- New CLI commands
Documentation is in `docs/`:
```
docs/
├── getting-started/ # Installation, quick start
├── user-guide/ # Feature documentation
└── developer-guide/ # This documentation
```
## Questions?
- Open an issue for questions
- Check existing issues first
- Be specific and provide context
## License
By contributing, you agree that your contributions will be licensed under the MIT License.
Thank you for contributing to PicoClaw!

View file

@ -0,0 +1,383 @@
# Data Flow and Message Bus
This document explains how messages flow through PicoClaw's message bus architecture.
## Message Bus Overview
The message bus is the central communication hub in PicoClaw. It decouples channels (which receive external messages) from the agent loop (which processes them).
### Message Types
```go
// InboundMessage represents a message from an external platform
type InboundMessage struct {
Channel string // Platform identifier (e.g., "telegram", "discord")
SenderID string // User identifier on the platform
ChatID string // Chat/conversation identifier
Content string // Message text content
Media []string // Optional media URLs or file paths
SessionKey string // Optional pre-computed session key
Metadata map[string]string // Additional platform-specific metadata
}
// OutboundMessage represents a response to be sent
type OutboundMessage struct {
Channel string // Target channel
ChatID string // Target chat/conversation
Content string // Response content
}
```
## Message Flow Diagram
```
┌─────────────────────────────────────────────────────────────────────────┐
│ External Platform │
│ (e.g., Telegram) │
└─────────────────────────────────────┬───────────────────────────────────┘
│ User sends message
┌─────────────────────────────────────────────────────────────────────────┐
│ Telegram Channel │
│ │
│ 1. Receive update from Telegram API │
│ 2. Extract sender, chat, content │
│ 3. Call HandleMessage() │
└─────────────────────────────────────┬───────────────────────────────────┘
│ bus.PublishInbound(msg)
┌─────────────────────────────────────────────────────────────────────────┐
│ Message Bus │
│ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ Inbound Channel (buffer: 100) │ │
│ │ │ │
│ │ InboundMessage{Channel:"telegram", ChatID:"123", ...} │ │
│ └─────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────┬───────────────────────────────────┘
│ bus.ConsumeInbound(ctx)
┌─────────────────────────────────────────────────────────────────────────┐
│ Agent Loop │
│ │
│ ┌────────────────────────────────────────────────────────────────┐ │
│ │ 1. Consume from inbound bus │ │
│ │ 2. Route to appropriate agent │ │
│ │ 3. Build context (history, system prompt, skills) │ │
│ │ 4. Call LLM provider │ │
│ │ 5. Handle tool calls (if any) │ │
│ │ 6. Save to session │ │
│ │ 7. Publish response to outbound bus │ │
│ └────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────┬───────────────────────────────────┘
│ bus.PublishOutbound(msg)
┌─────────────────────────────────────────────────────────────────────────┐
│ Message Bus │
│ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ Outbound Channel (buffer: 100) │ │
│ │ │ │
│ │ OutboundMessage{Channel:"telegram", ChatID:"123", ...} │ │
│ └─────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────┬───────────────────────────────────┘
│ bus.SubscribeOutbound(ctx)
┌─────────────────────────────────────────────────────────────────────────┐
│ Telegram Channel │
│ │
│ 1. Receive outbound message │
│ 2. Send via Telegram API │
└─────────────────────────────────────┬───────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────┐
│ External Platform │
│ (e.g., Telegram) │
│ │
│ User receives response │
└─────────────────────────────────────────────────────────────────────────┘
```
## Detailed Flow
### 1. Inbound Message Processing
When a message arrives from an external platform:
```go
// In the channel implementation (e.g., telegram.go)
func (c *TelegramChannel) handleUpdate(update tgbotapi.Update) {
// Extract message details
senderID := strconv.FormatInt(update.Message.From.ID, 10)
chatID := strconv.FormatInt(update.Message.Chat.ID, 10)
content := update.Message.Text
// Publish to message bus
c.HandleMessage(senderID, chatID, content, nil, nil)
}
// In BaseChannel
func (c *BaseChannel) HandleMessage(senderID, chatID, content string,
media []string, metadata map[string]string) {
if !c.IsAllowed(senderID) {
return // Skip unauthorized users
}
msg := bus.InboundMessage{
Channel: c.name,
SenderID: senderID,
ChatID: chatID,
Content: content,
Media: media,
Metadata: metadata,
}
c.bus.PublishInbound(msg)
}
```
### 2. Agent Loop Processing
The agent loop continuously processes messages:
```go
func (al *AgentLoop) Run(ctx context.Context) error {
al.running.Store(true)
for al.running.Load() {
select {
case <-ctx.Done():
return nil
default:
// Consume message from bus
msg, ok := al.bus.ConsumeInbound(ctx)
if !ok {
continue
}
// Process the message
response, err := al.processMessage(ctx, msg)
if err != nil {
response = fmt.Sprintf("Error: %v", err)
}
// Publish response
if response != "" {
al.bus.PublishOutbound(bus.OutboundMessage{
Channel: msg.Channel,
ChatID: msg.ChatID,
Content: response,
})
}
}
}
return nil
}
```
### 3. Message Routing
Messages are routed to appropriate agents:
```go
func (al *AgentLoop) processMessage(ctx context.Context, msg bus.InboundMessage) (string, error) {
// Route to determine agent and session key
route := al.registry.ResolveRoute(routing.RouteInput{
Channel: msg.Channel,
AccountID: msg.Metadata["account_id"],
Peer: extractPeer(msg),
ParentPeer: extractParentPeer(msg),
GuildID: msg.Metadata["guild_id"],
TeamID: msg.Metadata["team_id"],
})
agent, ok := al.registry.GetAgent(route.AgentID)
if !ok {
agent = al.registry.GetDefaultAgent()
}
return al.runAgentLoop(ctx, agent, processOptions{
SessionKey: route.SessionKey,
Channel: msg.Channel,
ChatID: msg.ChatID,
UserMessage: msg.Content,
})
}
```
### 4. Context Building
The context builder assembles the LLM prompt:
```go
messages := agent.ContextBuilder.BuildMessages(
history, // Previous messages from session
summary, // Summary of older messages (if any)
userMessage, // Current user message
nil, // Additional context
channel, // Current channel
chatID, // Current chat ID
)
```
The built messages include:
1. System prompt (from AGENT.md, IDENTITY.md, etc.)
2. Available tools list
3. Available skills
4. Session summary (if exists)
5. Conversation history
6. Current user message
### 5. LLM Call with Fallback
```go
// With fallback chain
if len(agent.Candidates) > 1 && al.fallback != nil {
fbResult, err := al.fallback.Execute(ctx, agent.Candidates,
func(ctx context.Context, provider, model string) (*LLMResponse, error) {
return agent.Provider.Chat(ctx, messages, tools, model, options)
},
)
// Handle result...
}
```
### 6. Tool Execution
When the LLM returns tool calls:
```go
for _, tc := range response.ToolCalls {
// Execute the tool with context
toolResult := agent.Tools.ExecuteWithContext(
ctx,
tc.Name,
tc.Arguments,
channel,
chatID,
asyncCallback, // For async tools
)
// Send ForUser content immediately if not silent
if !toolResult.Silent && toolResult.ForUser != "" {
al.bus.PublishOutbound(bus.OutboundMessage{
Channel: channel,
ChatID: chatID,
Content: toolResult.ForUser,
})
}
// Add tool result to messages for next LLM call
messages = append(messages, providers.Message{
Role: "tool",
Content: toolResult.ForLLM,
ToolCallID: tc.ID,
})
}
```
### 7. Outbound Message Handling
Channels subscribe to outbound messages:
```go
// In gateway main loop
for {
select {
case <-ctx.Done():
return
case msg, ok := msgBus.SubscribeOutbound(ctx):
if !ok {
continue
}
// Get the appropriate channel
channel, exists := channelManager.GetChannel(msg.Channel)
if !exists {
continue
}
// Send via channel
channel.Send(ctx, msg)
}
}
```
## Session Key Management
Session keys uniquely identify conversations:
```
Format: "channel:chatID" or "agent:agentID:channel:chatID"
Examples:
- "telegram:123456789" # Telegram private chat
- "telegram:-1001234567890" # Telegram group
- "discord:123456789012345678" # Discord channel
- "agent:main:telegram:123456" # Agent-specific session
```
## Async Tool Flow
Some tools (like spawn) operate asynchronously:
```
1. Tool receives Execute() call
2. Tool returns AsyncResult immediately
3. Tool starts work in goroutine
4. When complete, tool calls AsyncCallback
5. Callback publishes result via PublishInbound
6. AgentLoop processes result in next iteration
```
## Error Handling
Errors are handled at multiple levels:
1. **Channel level**: Connection errors, API errors
2. **Bus level**: Full buffer, closed channel
3. **Agent level**: LLM errors, tool errors
4. **Session level**: Save/load errors
Error responses are sent to users when appropriate:
```go
if err != nil {
response = fmt.Sprintf("Error processing message: %v", err)
}
```
## Graceful Shutdown
The message bus supports graceful shutdown:
```go
// Stop accepting new messages
mb.Close()
// AgentLoop checks running flag
for al.running.Load() {
// ...
}
// Context cancellation for in-flight operations
ctx, cancel := context.WithCancel(context.Background())
// ... on shutdown ...
cancel()
```
## Performance Characteristics
- **Buffer capacity**: 100 messages per channel
- **Concurrency**: Multiple channels can publish simultaneously
- **Thread safety**: All operations are thread-safe via mutex
- **Memory**: Messages are held in memory until processed
## Best Practices
1. **Always check context cancellation** in long-running operations
2. **Use timeouts** for external API calls
3. **Handle full buffers** gracefully
4. **Log message processing** for debugging
5. **Don't block** the message bus with slow operations

View file

@ -0,0 +1,152 @@
# Extending PicoClaw
This directory contains guides for extending PicoClaw with custom functionality.
## Overview
PicoClaw is designed to be extensible. The main extension points are:
1. **Tools** - Add new capabilities for the agent to use
2. **LLM Providers** - Add support for new LLM APIs
3. **Channels** - Add integrations with new chat platforms
4. **Skills** - Create reusable prompt templates
## Extension Points
### [Creating Custom Tools](creating-tools.md)
Tools are the primary way agents interact with the world. Create custom tools to:
- Integrate with external APIs
- Add domain-specific functionality
- Interact with local systems
Example use cases:
- Database queries
- File format conversion
- API integrations
- Custom calculations
### [Creating LLM Providers](creating-providers.md)
Providers handle communication with LLM APIs. Create new providers to:
- Support new LLM services
- Implement custom authentication
- Add specialized request/response handling
Example use cases:
- New AI service integrations
- Local LLM support
- Custom API gateways
### [Creating Channel Integrations](creating-channels.md)
Channels connect PicoClaw to chat platforms. Create new channels to:
- Support new messaging platforms
- Add custom communication protocols
- Integrate with internal systems
Example use cases:
- Team chat platforms
- Custom bots
- Internal communication systems
### [Creating Skills](creating-skills.md)
Skills are reusable prompt templates. Create skills to:
- Package domain expertise
- Create reusable workflows
- Share capabilities across agents
Example use cases:
- Code review assistance
- Document analysis
- Domain-specific knowledge
## Architecture for Extensions
```
┌─────────────────────────────────────────────────────────────┐
│ Agent Loop │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Tools │ │ Provider │ │ Channels │ │
│ │ Registry │ │ Factory │ │ Manager │ │
│ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Custom Tool │ │ Custom │ │ Custom │ │
│ │ (Yours) │ │ Provider │ │ Channel │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────────┘
```
## Getting Started
Choose an extension type based on what you want to accomplish:
| Goal | Extension Type | Guide |
|------|---------------|-------|
| Add new capabilities | Tool | [Creating Tools](creating-tools.md) |
| Use new LLM service | Provider | [Creating Providers](creating-providers.md) |
| Connect new platform | Channel | [Creating Channels](creating-channels.md) |
| Share prompts | Skill | [Creating Skills](creating-skills.md) |
## Quick Reference
### Tool Interface
```go
type Tool interface {
Name() string
Description() string
Parameters() map[string]interface{}
Execute(ctx context.Context, args map[string]interface{}) *ToolResult
}
```
### Provider Interface
```go
type LLMProvider interface {
Chat(ctx context.Context, messages []Message, tools []ToolDefinition,
model string, options map[string]interface{}) (*LLMResponse, error)
GetDefaultModel() string
}
```
### Channel Interface
```go
type Channel interface {
Name() string
Start(ctx context.Context) error
Stop(ctx context.Context) error
Send(ctx context.Context, msg bus.OutboundMessage) error
IsRunning() bool
IsAllowed(senderID string) bool
}
```
## Development Workflow
1. **Plan** - Define what you want to build
2. **Implement** - Create the extension following the guide
3. **Test** - Write tests for your extension
4. **Integrate** - Register your extension with PicoClaw
5. **Document** - Add documentation for users
## Contributing Extensions
If you create a useful extension, consider contributing it back:
1. Fork the repository
2. Add your extension
3. Add tests
4. Submit a pull request
See [Contributing Guidelines](../contributing.md) for details.

View file

@ -0,0 +1,569 @@
# Creating Channel Integrations
This guide explains how to create channel integrations for PicoClaw.
## Overview
Channels connect PicoClaw to external chat platforms like Telegram, Discord, Slack, etc. Each channel implements the `Channel` interface and is responsible for:
1. Receiving messages from the platform
2. Publishing them to the message bus
3. Subscribing to outbound messages
4. Sending responses to the platform
## Channel Interface
All channels must implement this interface:
```go
type Channel interface {
Name() string
Start(ctx context.Context) error
Stop(ctx context.Context) error
Send(ctx context.Context, msg bus.OutboundMessage) error
IsRunning() bool
IsAllowed(senderID string) bool
}
```
## Base Channel
PicoClaw provides a `BaseChannel` struct that handles common functionality:
```go
type BaseChannel struct {
config interface{}
bus *bus.MessageBus
running bool
name string
allowList []string
}
// HandleMessage publishes a message to the bus
func (c *BaseChannel) HandleMessage(senderID, chatID, content string,
media []string, metadata map[string]string)
// IsAllowed checks if sender is in the allowlist
func (c *BaseChannel) IsAllowed(senderID string) bool
// Name returns the channel name
func (c *BaseChannel) Name() string
// IsRunning returns the running state
func (c *BaseChannel) IsRunning() bool
```
## Creating a Basic Channel
### Step 1: Define the Channel Struct
```go
package channels
import (
"context"
"fmt"
"sync"
"github.com/sipeed/picoclaw/pkg/bus"
)
// MyChannelConfig holds channel configuration
type MyChannelConfig struct {
APIToken string `json:"api_token"`
AllowList []string `json:"allow_list"`
}
// MyChannel implements the Channel interface
type MyChannel struct {
*BaseChannel // Embed base functionality
config *MyChannelConfig
client *MyAPIClient
mu sync.Mutex
}
```
### Step 2: Create Constructor
```go
func NewMyChannel(cfg *MyChannelConfig, msgBus *bus.MessageBus) *MyChannel {
return &MyChannel{
BaseChannel: NewBaseChannel("mychannel", cfg, msgBus, cfg.AllowList),
config: cfg,
client: NewMyAPIClient(cfg.APIToken),
}
}
```
### Step 3: Implement Start
```go
func (c *MyChannel) Start(ctx context.Context) error {
c.mu.Lock()
defer c.mu.Unlock()
if c.running {
return nil
}
// Start receiving messages from the platform
go c.receiveLoop(ctx)
c.setRunning(true)
return nil
}
func (c *MyChannel) receiveLoop(ctx context.Context) {
// Subscribe to platform updates
updates, err := c.client.Subscribe(ctx)
if err != nil {
// Handle error
return
}
for {
select {
case <-ctx.Done():
return
case update, ok := <-updates:
if !ok {
return
}
c.handleUpdate(update)
}
}
}
```
### Step 4: Implement Stop
```go
func (c *MyChannel) Stop(ctx context.Context) error {
c.mu.Lock()
defer c.mu.Unlock()
if !c.running {
return nil
}
// Close client connections
if err := c.client.Close(); err != nil {
return fmt.Errorf("failed to close client: %w", err)
}
c.setRunning(false)
return nil
}
```
### Step 5: Implement Send
```go
func (c *MyChannel) Send(ctx context.Context, msg bus.OutboundMessage) error {
if !c.running {
return fmt.Errorf("channel not running")
}
// Send message through platform API
return c.client.SendMessage(ctx, msg.ChatID, msg.Content)
}
```
### Step 6: Handle Incoming Messages
```go
func (c *MyChannel) handleUpdate(update MyUpdate) {
// Extract message details
senderID := update.Sender.ID
chatID := update.Chat.ID
content := update.Message.Text
// Collect media if present
var media []string
if update.Message.Attachment != "" {
media = append(media, update.Message.Attachment)
}
// Build metadata
metadata := map[string]string{
"message_id": update.ID,
"timestamp": update.Timestamp,
}
// Publish to message bus
c.HandleMessage(senderID, chatID, content, media, metadata)
}
```
## Complete Example: WebSocket Channel
```go
package channels
import (
"context"
"encoding/json"
"fmt"
"sync"
"github.com/gorilla/websocket"
"github.com/sipeed/picoclaw/pkg/bus"
)
type WebSocketConfig struct {
URL string `json:"url"`
Token string `json:"token"`
AllowList []string `json:"allow_list"`
}
type WebSocketChannel struct {
*BaseChannel
config *WebSocketConfig
conn *websocket.Conn
mu sync.Mutex
sendCh chan bus.OutboundMessage
}
func NewWebSocketChannel(cfg *WebSocketConfig, msgBus *bus.MessageBus) *WebSocketChannel {
return &WebSocketChannel{
BaseChannel: NewBaseChannel("websocket", cfg, msgBus, cfg.AllowList),
config: cfg,
sendCh: make(chan bus.OutboundMessage, 100),
}
}
func (c *WebSocketChannel) Start(ctx context.Context) error {
c.mu.Lock()
defer c.mu.Unlock()
if c.running {
return nil
}
// Connect to WebSocket server
headers := make(map[string][]string)
if c.config.Token != "" {
headers["Authorization"] = []string{"Bearer " + c.config.Token}
}
conn, _, err := websocket.DefaultDialer.Dial(c.config.URL, headers)
if err != nil {
return fmt.Errorf("failed to connect: %w", err)
}
c.conn = conn
// Start receive goroutine
go c.receiveLoop(ctx)
// Start send goroutine
go c.sendLoop(ctx)
c.setRunning(true)
return nil
}
func (c *WebSocketChannel) Stop(ctx context.Context) error {
c.mu.Lock()
defer c.mu.Unlock()
if !c.running {
return nil
}
// Close send channel
close(c.sendCh)
// Close connection
if c.conn != nil {
c.conn.Close()
}
c.setRunning(false)
return nil
}
func (c *WebSocketChannel) Send(ctx context.Context, msg bus.OutboundMessage) error {
if !c.running {
return fmt.Errorf("channel not running")
}
select {
case c.sendCh <- msg:
return nil
default:
return fmt.Errorf("send buffer full")
}
}
func (c *WebSocketChannel) receiveLoop(ctx context.Context) {
for {
select {
case <-ctx.Done():
return
default:
_, message, err := c.conn.ReadMessage()
if err != nil {
// Handle error - reconnect?
return
}
c.handleMessage(message)
}
}
}
func (c *WebSocketChannel) sendLoop(ctx context.Context) {
for {
select {
case <-ctx.Done():
return
case msg, ok := <-c.sendCh:
if !ok {
return
}
// Create WebSocket message
wsMsg := map[string]interface{}{
"chat_id": msg.ChatID,
"content": msg.Content,
}
data, _ := json.Marshal(wsMsg)
if err := c.conn.WriteMessage(websocket.TextMessage, data); err != nil {
// Handle error
}
}
}
}
func (c *WebSocketChannel) handleMessage(data []byte) {
var msg struct {
SenderID string `json:"sender_id"`
ChatID string `json:"chat_id"`
Content string `json:"content"`
}
if err := json.Unmarshal(data, &msg); err != nil {
return
}
// Publish to bus
c.HandleMessage(msg.SenderID, msg.ChatID, msg.Content, nil, nil)
}
```
## Registering Channels
Channels are registered in the channel manager:
```go
// In gateway setup
channelManager := channels.NewManager()
// Add your channel
myChannel := channels.NewMyChannel(&config.Channels.MyChannel, msgBus)
channelManager.Register(myChannel)
// Start all channels
channelManager.StartAll(ctx)
```
## Handling Rich Media
### Receiving Media
```go
func (c *MyChannel) handleUpdate(update MyUpdate) {
var media []string
// Collect images
for _, img := range update.Message.Images {
media = append(media, img.URL)
}
// Collect files
for _, file := range update.Message.Files {
media = append(media, file.URL)
}
c.HandleMessage(senderID, chatID, content, media, metadata)
}
```
### Sending Media
Some platforms support rich message formatting:
```go
func (c *MyChannel) Send(ctx context.Context, msg bus.OutboundMessage) error {
// Check for markdown support
if supportsMarkdown(msg.Content) {
return c.client.SendMarkdown(ctx, msg.ChatID, msg.Content)
}
// Plain text fallback
return c.client.SendMessage(ctx, msg.ChatID, msg.Content)
}
```
## Metadata
Use metadata to pass platform-specific information:
```go
metadata := map[string]string{
"message_id": update.ID,
"reply_to_id": update.ReplyToID,
"peer_kind": "direct", // or "group", "channel"
"peer_id": update.Chat.ID,
"account_id": c.accountID,
"guild_id": update.GuildID, // For Discord-like platforms
"team_id": update.TeamID, // For Slack-like platforms
}
c.HandleMessage(senderID, chatID, content, media, metadata)
```
This metadata is used for:
- Message routing
- Reply threading
- Multi-account support
## Configuration
Add your channel configuration to the config structure:
```go
// In pkg/config/config.go
type ChannelsConfig struct {
Telegram TelegramConfig `json:"telegram"`
Discord DiscordConfig `json:"discord"`
MyChannel MyChannelConfig `json:"mychannel"`
// ...
}
```
Example configuration:
```json
{
"channels": {
"mychannel": {
"api_token": "your-token-here",
"allow_list": ["user1", "user2"]
}
}
}
```
## Error Handling
Handle errors gracefully:
```go
func (c *MyChannel) receiveLoop(ctx context.Context) {
defer func() {
if r := recover(); r != nil {
// Log panic and attempt recovery
}
}()
for {
select {
case <-ctx.Done():
return
default:
if err := c.receiveMessage(ctx); err != nil {
// Log error
if isConnectionError(err) {
// Attempt reconnection
c.reconnect(ctx)
}
}
}
}
}
```
## Testing Channels
```go
package channels
import (
"context"
"testing"
"github.com/sipeed/picoclaw/pkg/bus"
)
func TestMyChannel(t *testing.T) {
// Create message bus
msgBus := bus.NewMessageBus()
// Create channel
cfg := &MyChannelConfig{
APIToken: "test-token",
}
channel := NewMyChannel(cfg, msgBus)
// Test name
if channel.Name() != "mychannel" {
t.Errorf("expected name 'mychannel', got %s", channel.Name())
}
// Test start/stop
ctx := context.Background()
if err := channel.Start(ctx); err != nil {
t.Fatalf("failed to start: %v", err)
}
if !channel.IsRunning() {
t.Error("channel should be running")
}
if err := channel.Stop(ctx); err != nil {
t.Fatalf("failed to stop: %v", err)
}
if channel.IsRunning() {
t.Error("channel should not be running")
}
}
func TestAllowList(t *testing.T) {
msgBus := bus.NewMessageBus()
cfg := &MyChannelConfig{
APIToken: "test-token",
AllowList: []string{"user1", "user2"},
}
channel := NewMyChannel(cfg, msgBus)
// Test allowed users
if !channel.IsAllowed("user1") {
t.Error("user1 should be allowed")
}
// Test disallowed users
if channel.IsAllowed("user3") {
t.Error("user3 should not be allowed")
}
}
```
## Best Practices
1. **Graceful Shutdown**: Handle context cancellation properly
2. **Reconnection**: Implement automatic reconnection for network issues
3. **Rate Limiting**: Respect platform rate limits
4. **Error Logging**: Log errors for debugging
5. **Buffer Sizes**: Use appropriate buffer sizes for channels
6. **Thread Safety**: Use mutexes for shared state
7. **Backpressure**: Handle slow consumers gracefully
## See Also
- [Message Bus API](../api/message-bus.md)
- [Existing Channels](https://github.com/sipeed/picoclaw/tree/main/pkg/channels)
- [Telegram Channel](https://github.com/sipeed/picoclaw/tree/main/pkg/channels/telegram.go)

View file

@ -0,0 +1,636 @@
# Creating LLM Providers
This guide explains how to create custom LLM providers for PicoClaw.
## Overview
LLM providers handle communication with language model APIs. Each provider implements the `LLMProvider` interface and is responsible for:
1. Formatting requests for the specific API
2. Sending requests to the API
3. Parsing responses and tool calls
4. Handling errors and retries
## LLMProvider Interface
All providers must implement this interface:
```go
type LLMProvider interface {
Chat(ctx context.Context, messages []Message, tools []ToolDefinition,
model string, options map[string]interface{}) (*LLMResponse, error)
GetDefaultModel() string
}
```
### Supporting Types
```go
// Message represents a chat message
type Message struct {
Role string `json:"role"` // "system", "user", "assistant", "tool"
Content string `json:"content"` // Message content
ToolCalls []ToolCall `json:"tool_calls,omitempty"` // Tool calls from assistant
ToolCallID string `json:"tool_call_id,omitempty"` // ID for tool response
}
// ToolCall represents a tool call request
type ToolCall struct {
ID string `json:"id"`
Type string `json:"type,omitempty"`
Function *FunctionCall `json:"function,omitempty"`
Name string `json:"name,omitempty"`
Arguments map[string]interface{} `json:"arguments,omitempty"`
}
// FunctionCall represents function call details
type FunctionCall struct {
Name string `json:"name"`
Arguments string `json:"arguments"` // JSON string
}
// LLMResponse is the response from the LLM
type LLMResponse struct {
Content string `json:"content"`
ToolCalls []ToolCall `json:"tool_calls,omitempty"`
FinishReason string `json:"finish_reason"`
Usage *UsageInfo `json:"usage,omitempty"`
}
// UsageInfo contains token usage information
type UsageInfo struct {
PromptTokens int `json:"prompt_tokens"`
CompletionTokens int `json:"completion_tokens"`
TotalTokens int `json:"total_tokens"`
}
// ToolDefinition defines a tool for the LLM
type ToolDefinition struct {
Type string `json:"type"`
Function ToolFunctionDefinition `json:"function"`
}
// ToolFunctionDefinition describes a tool function
type ToolFunctionDefinition struct {
Name string `json:"name"`
Description string `json:"description"`
Parameters map[string]interface{} `json:"parameters"`
}
```
## Creating a Basic Provider
### Step 1: Define the Provider Struct
```go
package myprovider
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"time"
"github.com/sipeed/picoclaw/pkg/providers/protocoltypes"
)
type Provider struct {
apiKey string
apiBase string
httpClient *http.Client
}
func NewProvider(apiKey, apiBase string) *Provider {
return &Provider{
apiKey: apiKey,
apiBase: apiBase,
httpClient: &http.Client{
Timeout: 120 * time.Second,
},
}
}
```
### Step 2: Implement GetDefaultModel
```go
func (p *Provider) GetDefaultModel() string {
return "my-provider/default-model"
}
```
### Step 3: Implement Chat
```go
func (p *Provider) Chat(ctx context.Context, messages []protocoltypes.Message,
tools []protocoltypes.ToolDefinition, model string,
options map[string]interface{}) (*protocoltypes.LLMResponse, error) {
// Build request body
requestBody := map[string]interface{}{
"model": model,
"messages": messages,
}
// Add tools if provided
if len(tools) > 0 {
requestBody["tools"] = tools
requestBody["tool_choice"] = "auto"
}
// Add options
if maxTokens, ok := options["max_tokens"]; ok {
requestBody["max_tokens"] = maxTokens
}
if temperature, ok := options["temperature"]; ok {
requestBody["temperature"] = temperature
}
// Marshal request
jsonData, err := json.Marshal(requestBody)
if err != nil {
return nil, fmt.Errorf("failed to marshal request: %w", err)
}
// Create HTTP request
req, err := http.NewRequestWithContext(ctx, "POST",
p.apiBase+"/chat/completions", bytes.NewReader(jsonData))
if err != nil {
return nil, fmt.Errorf("failed to create request: %w", err)
}
// Set headers
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer "+p.apiKey)
// Send request
resp, err := p.httpClient.Do(req)
if err != nil {
return nil, fmt.Errorf("failed to send request: %w", err)
}
defer resp.Body.Close()
// Read response
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("failed to read response: %w", err)
}
// Check status code
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("API error: status=%d body=%s", resp.StatusCode, string(body))
}
// Parse response
return p.parseResponse(body)
}
```
### Step 4: Implement Response Parsing
```go
func (p *Provider) parseResponse(body []byte) (*protocoltypes.LLMResponse, error) {
// Define response structure matching the API
var apiResponse struct {
Choices []struct {
Message struct {
Content string `json:"content"`
ToolCalls []struct {
ID string `json:"id"`
Type string `json:"type"`
Function *struct {
Name string `json:"name"`
Arguments string `json:"arguments"`
} `json:"function"`
} `json:"tool_calls"`
} `json:"message"`
FinishReason string `json:"finish_reason"`
} `json:"choices"`
Usage *protocoltypes.UsageInfo `json:"usage"`
}
// Parse JSON
if err := json.Unmarshal(body, &apiResponse); err != nil {
return nil, fmt.Errorf("failed to unmarshal response: %w", err)
}
// Handle empty response
if len(apiResponse.Choices) == 0 {
return &protocoltypes.LLMResponse{
Content: "",
FinishReason: "stop",
}, nil
}
// Extract choice
choice := apiResponse.Choices[0]
// Convert tool calls
toolCalls := make([]protocoltypes.ToolCall, 0, len(choice.Message.ToolCalls))
for _, tc := range choice.Message.ToolCalls {
arguments := make(map[string]interface{})
name := ""
if tc.Function != nil {
name = tc.Function.Name
if tc.Function.Arguments != "" {
if err := json.Unmarshal([]byte(tc.Function.Arguments), &arguments); err != nil {
// Handle parse error - store raw arguments
arguments["raw"] = tc.Function.Arguments
}
}
}
toolCalls = append(toolCalls, protocoltypes.ToolCall{
ID: tc.ID,
Name: name,
Arguments: arguments,
})
}
return &protocoltypes.LLMResponse{
Content: choice.Message.Content,
ToolCalls: toolCalls,
FinishReason: choice.FinishReason,
Usage: apiResponse.Usage,
}, nil
}
```
## Error Classification
For fallback chain support, classify errors:
```go
import "github.com/sipeed/picoclaw/pkg/providers"
func (p *Provider) Chat(ctx context.Context, messages []protocoltypes.Message,
tools []protocoltypes.ToolDefinition, model string,
options map[string]interface{}) (*protocoltypes.LLMResponse, error) {
// ... make request ...
if resp.StatusCode != http.StatusOK {
// Classify error
reason := p.classifyError(resp.StatusCode, body)
return nil, &providers.FailoverError{
Reason: reason,
Provider: "myprovider",
Model: model,
Status: resp.StatusCode,
Wrapped: fmt.Errorf("API error: %s", string(body)),
}
}
// ...
}
func (p *Provider) classifyError(status int, body []byte) providers.FailoverReason {
switch status {
case 401, 403:
return providers.FailoverAuth
case 429:
return providers.FailoverRateLimit
case 402:
return providers.FailoverBilling
case 504, 502:
return providers.FailoverTimeout
case 503:
return providers.FailoverOverloaded
case 400:
return providers.FailoverFormat
default:
return providers.FailoverUnknown
}
}
```
## Registering Providers
Add your provider to the factory:
```go
// In pkg/providers/factory.go
func NewProviderFromConfig(cfg *config.Config) (LLMProvider, error) {
// ... existing checks ...
// Add your provider
if cfg.Providers.MyProvider.APIKey != "" {
return myprovider.NewProvider(
cfg.Providers.MyProvider.APIKey,
cfg.Providers.MyProvider.APIBase,
), nil
}
// ...
}
```
## Complete Example: Custom Provider
```go
package myprovider
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"time"
"github.com/sipeed/picoclaw/pkg/providers"
"github.com/sipeed/picoclaw/pkg/providers/protocoltypes"
)
type Provider struct {
apiKey string
apiBase string
httpClient *http.Client
defaultModel string
}
type Config struct {
APIKey string
APIBase string
DefaultModel string
Timeout time.Duration
Proxy string
}
func NewProvider(cfg Config) *Provider {
client := &http.Client{
Timeout: cfg.Timeout,
}
if cfg.Timeout == 0 {
client.Timeout = 120 * time.Second
}
if cfg.APIBase == "" {
cfg.APIBase = "https://api.myprovider.com/v1"
}
if cfg.DefaultModel == "" {
cfg.DefaultModel = "myprovider/default"
}
return &Provider{
apiKey: cfg.APIKey,
apiBase: cfg.APIBase,
httpClient: client,
defaultModel: cfg.DefaultModel,
}
}
func (p *Provider) GetDefaultModel() string {
return p.defaultModel
}
func (p *Provider) Chat(ctx context.Context, messages []protocoltypes.Message,
tools []protocoltypes.ToolDefinition, model string,
options map[string]interface{}) (*protocoltypes.LLMResponse, error) {
if p.apiKey == "" {
return nil, fmt.Errorf("API key not configured")
}
// Normalize model name (strip provider prefix if present)
model = normalizeModel(model)
// Build request
requestBody := p.buildRequestBody(messages, tools, model, options)
// Marshal
jsonData, err := json.Marshal(requestBody)
if err != nil {
return nil, fmt.Errorf("marshal request: %w", err)
}
// Create request
url := p.apiBase + "/chat/completions"
req, err := http.NewRequestWithContext(ctx, "POST", url, bytes.NewReader(jsonData))
if err != nil {
return nil, fmt.Errorf("create request: %w", err)
}
// Set headers
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer "+p.apiKey)
// Send
resp, err := p.httpClient.Do(req)
if err != nil {
return nil, fmt.Errorf("send request: %w", err)
}
defer resp.Body.Close()
// Read body
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("read response: %w", err)
}
// Handle errors
if resp.StatusCode != http.StatusOK {
return nil, p.createError(resp.StatusCode, body, model)
}
// Parse response
return p.parseResponse(body)
}
func (p *Provider) buildRequestBody(messages []protocoltypes.Message,
tools []protocoltypes.ToolDefinition, model string,
options map[string]interface{}) map[string]interface{} {
body := map[string]interface{}{
"model": model,
"messages": messages,
}
if len(tools) > 0 {
body["tools"] = tools
body["tool_choice"] = "auto"
}
if maxTokens, ok := asInt(options["max_tokens"]); ok {
body["max_tokens"] = maxTokens
}
if temperature, ok := asFloat(options["temperature"]); ok {
body["temperature"] = temperature
}
return body
}
func (p *Provider) createError(status int, body []byte, model string) error {
reason := providers.FailoverUnknown
switch status {
case 401, 403:
reason = providers.FailoverAuth
case 429:
reason = providers.FailoverRateLimit
case 402:
reason = providers.FailoverBilling
case 504, 502:
reason = providers.FailoverTimeout
case 503:
reason = providers.FailoverOverloaded
case 400:
reason = providers.FailoverFormat
}
return &providers.FailoverError{
Reason: reason,
Provider: "myprovider",
Model: model,
Status: status,
Wrapped: fmt.Errorf("API error: %s", string(body)),
}
}
func normalizeModel(model string) string {
// Strip "myprovider/" prefix if present
if len(model) > 11 && model[:11] == "myprovider/" {
return model[11:]
}
return model
}
func asInt(v interface{}) (int, bool) {
switch val := v.(type) {
case int:
return val, true
case int64:
return int(val), true
case float64:
return int(val), true
default:
return 0, false
}
}
func asFloat(v interface{}) (float64, bool) {
switch val := v.(type) {
case float64:
return val, true
case float32:
return float64(val), true
case int:
return float64(val), true
default:
return 0, false
}
}
```
## Testing Providers
```go
package myprovider
import (
"context"
"net/http"
"net/http/httptest"
"testing"
"github.com/sipeed/picoclaw/pkg/providers/protocoltypes"
)
func TestProviderChat(t *testing.T) {
// Create test server
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Verify request
if r.Header.Get("Authorization") != "Bearer test-key" {
t.Error("missing authorization header")
}
// Send mock response
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
w.Write([]byte(`{
"choices": [{
"message": {
"content": "Hello!",
"tool_calls": []
},
"finish_reason": "stop"
}],
"usage": {
"prompt_tokens": 10,
"completion_tokens": 5,
"total_tokens": 15
}
}`))
}))
defer server.Close()
// Create provider
provider := NewProvider(Config{
APIKey: "test-key",
APIBase: server.URL,
})
// Test chat
messages := []protocoltypes.Message{
{Role: "user", Content: "Hi"},
}
resp, err := provider.Chat(context.Background(), messages, nil, "test-model", nil)
if err != nil {
t.Fatalf("Chat failed: %v", err)
}
if resp.Content != "Hello!" {
t.Errorf("expected 'Hello!', got %q", resp.Content)
}
}
func TestProviderError(t *testing.T) {
// Create test server that returns error
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusUnauthorized)
w.Write([]byte(`{"error": "invalid API key"}`))
}))
defer server.Close()
provider := NewProvider(Config{
APIKey: "bad-key",
APIBase: server.URL,
})
messages := []protocoltypes.Message{
{Role: "user", Content: "Hi"},
}
_, err := provider.Chat(context.Background(), messages, nil, "test-model", nil)
if err == nil {
t.Error("expected error for 401 response")
}
}
```
## Best Practices
1. **Context Support**: Always use context for cancellation
2. **Error Classification**: Classify errors for fallback support
3. **Timeout Configuration**: Allow configurable timeouts
4. **Model Normalization**: Handle provider prefixes in model names
5. **Retry Logic**: Consider adding retry for transient errors
6. **Logging**: Log requests and responses for debugging
7. **Rate Limiting**: Respect API rate limits
## See Also
- [Provider Interface Reference](../api/provider-interface.md)
- [Fallback Chain](../api/provider-interface.md#fallback-chain)
- [OpenAI-Compatible Provider](https://github.com/sipeed/picoclaw/tree/main/pkg/providers/openai_compat)

View file

@ -0,0 +1,464 @@
# Creating Skills
This guide explains how to create skills for PicoClaw.
## Overview
Skills are reusable prompt templates that enhance the agent's capabilities. They are defined in Markdown files and can be loaded from multiple locations. Skills are a powerful way to:
- Package domain expertise
- Create reusable workflows
- Share capabilities across agents
- Customize agent behavior for specific tasks
## Skill File Format
Skills are defined in `SKILL.md` files with optional YAML frontmatter:
```markdown
---
name: code-review
description: Review code for quality, security, and best practices
---
# Code Review Skill
You are a code reviewer. When reviewing code, analyze:
## Code Quality
- Readability and maintainability
- Naming conventions
- Code organization
## Security
- Input validation
- Authentication/authorization
- Potential vulnerabilities
## Best Practices
- Design patterns
- Error handling
- Performance considerations
## Output Format
Provide your review in the following format:
### Summary
[Brief summary of the review]
### Issues Found
- [List of issues with severity]
### Recommendations
- [List of recommendations]
### Positive Aspects
- [Things done well]
```
## Skill Locations
Skills are loaded from three locations in priority order:
1. **Workspace Skills** (highest priority)
- Location: `~/.picoclaw/workspace/skills/<skill-name>/SKILL.md`
- Use: Project-specific skills
2. **Global Skills**
- Location: `~/.picoclaw/skills/<skill-name>/SKILL.md`
- Use: User-wide skills
3. **Built-in Skills** (lowest priority)
- Location: Embedded in binary or system directory
- Use: System-provided skills
When skills have the same name, higher-priority locations override lower ones.
## Creating a Skill
### Step 1: Create Skill Directory
```bash
mkdir -p ~/.picoclaw/skills/my-skill
```
### Step 2: Create SKILL.md
Create `~/.picoclaw/skills/my-skill/SILL.md`:
```markdown
---
name: my-skill
description: A brief description of what this skill does
---
# My Skill
[Detailed skill instructions go here]
```
### Step 3: Use in Agent
Skills are automatically discovered. The agent will see available skills and can invoke them.
## Skill Metadata
### Name
The skill name must:
- Be alphanumeric with hyphens
- Be at most 64 characters
- Match the pattern: `^[a-zA-Z0-9]+(-[a-zA-Z0-9]+)*$`
```yaml
---
name: valid-skill-name
---
```
### Description
The description should:
- Be at most 1024 characters
- Explain what the skill does
- Help the LLM decide when to use it
```yaml
---
description: Analyzes Python code for potential bugs and suggests improvements
---
```
## Skill Content
The skill content (after frontmatter) is injected into the system prompt when the skill is active. Write clear, detailed instructions:
### Good Skill Content
```markdown
# Database Query Skill
You are a database expert. When helping with database queries:
## Supported Databases
- PostgreSQL
- MySQL
- SQLite
## Query Guidelines
1. **Always use parameterized queries** to prevent SQL injection
2. **Include indexes** for frequently queried columns
3. **Use transactions** for multi-step operations
## Example Queries
### Select with Join
```sql
SELECT u.name, o.total
FROM users u
JOIN orders o ON u.id = o.user_id
WHERE o.created_at > ?
```
## Output Format
When generating SQL:
1. Explain what the query does
2. Show the SQL statement
3. List any assumptions made
```
### Tips for Effective Skills
1. **Be Specific**: Provide concrete examples and guidelines
2. **Structure Content**: Use headings, lists, and code blocks
3. **Define Scope**: Clearly state what the skill does and doesn't do
4. **Include Examples**: Show expected inputs and outputs
5. **Set Boundaries**: Define limitations and edge cases
## Example Skills
### Code Generation Skill
```markdown
---
name: code-gen
description: Generate high-quality code in various programming languages
---
# Code Generation Skill
Generate clean, well-documented code following these principles:
## Code Style
### Python
- Follow PEP 8
- Use type hints
- Document with docstrings
### JavaScript/TypeScript
- Use const/let (never var)
- Prefer arrow functions
- Use JSDoc comments
### Go
- Follow gofmt style
- Handle errors explicitly
- Use meaningful variable names
## Documentation
Always include:
- Purpose of the function/module
- Parameter descriptions
- Return value description
- Example usage
## Example
```python
def calculate_total(items: list[dict]) -> float:
"""
Calculate the total price of items.
Args:
items: List of item dictionaries with 'price' and 'quantity' keys.
Returns:
Total price as a float.
Example:
>>> items = [{'price': 10.0, 'quantity': 2}]
>>> calculate_total(items)
20.0
"""
return sum(item['price'] * item['quantity'] for item in items)
```
```
### Writing Assistant Skill
```markdown
---
name: writing-assistant
description: Help with writing, editing, and improving text
---
# Writing Assistant Skill
You are a writing assistant. Help users improve their writing.
## Services
### Editing
- Fix grammar and spelling
- Improve clarity
- Enhance readability
### Style Suggestions
- Adjust tone (formal/casual)
- Improve flow
- Strengthen word choice
### Structure
- Organize paragraphs
- Create outlines
- Develop arguments
## Guidelines
1. Preserve the author's voice
2. Explain significant changes
3. Offer alternatives for major revisions
4. Consider the target audience
## Output Format
When editing, provide:
1. **Revised text**: The improved version
2. **Changes made**: Brief explanation of edits
3. **Suggestions**: Optional further improvements
```
### Data Analysis Skill
```markdown
---
name: data-analysis
description: Analyze datasets and provide insights
---
# Data Analysis Skill
You are a data analyst. Help users understand their data.
## Capabilities
### Descriptive Statistics
- Mean, median, mode
- Standard deviation
- Distribution analysis
### Pattern Recognition
- Trends over time
- Correlations
- Anomalies
### Visualization Suggestions
- Chart types
- Color schemes
- Labeling best practices
## Analysis Process
1. **Understand the Data**
- What does each column represent?
- What is the time range?
- Are there missing values?
2. **Clean the Data**
- Handle nulls
- Remove duplicates
- Fix inconsistencies
3. **Analyze**
- Calculate statistics
- Find patterns
- Identify insights
4. **Report**
- Summarize findings
- Highlight key insights
- Recommend actions
## Output Format
### Executive Summary
[2-3 sentence overview]
### Key Findings
- [Finding 1]
- [Finding 2]
- [Finding 3]
### Detailed Analysis
[In-depth analysis]
### Recommendations
- [Recommendation 1]
- [Recommendation 2]
```
## Frontmatter Formats
PicoClaw supports both JSON and YAML frontmatter:
### YAML (Recommended)
```markdown
---
name: my-skill
description: Skill description
---
Content here...
```
### JSON
```markdown
---
{
"name": "my-skill",
"description": "Skill description"
}
---
Content here...
```
## Loading Skills
Skills are loaded by the `SkillsLoader`:
```go
loader := skills.NewSkillsLoader(
workspace, // Workspace directory
globalSkillsPath, // ~/.picoclaw/skills
builtinSkillsPath, // Built-in skills directory
)
// List all available skills
allSkills := loader.ListSkills()
// Load a specific skill
content, found := loader.LoadSkill("my-skill")
// Build summary for context
summary := loader.BuildSkillsSummary()
```
## Testing Skills
Test your skills by:
1. **Creating the skill file** in the appropriate directory
2. **Starting PicoClaw** with debug mode
3. **Asking the agent** about available skills
4. **Invoking the skill** with a relevant request
```bash
# Start with debug
./build/picoclaw agent --debug
# Ask about skills
> What skills do you have available?
> Use the code-review skill to review this function:
> def add(a, b): return a + b
```
## Best Practices
1. **Single Purpose**: Each skill should do one thing well
2. **Clear Description**: Help the LLM know when to use it
3. **Comprehensive Content**: Include all necessary context
4. **Examples**: Show expected inputs and outputs
5. **Limitations**: State what the skill cannot do
6. **Regular Updates**: Keep skills current with requirements
## Sharing Skills
Skills can be shared by:
1. **Git Repository**: Store skills in a repo
2. **Copy to Workspace**: Copy skill directories
3. **Package Distribution**: Create skill packages
Example structure for a skill repository:
```
my-skills/
├── code-review/
│ └── SKILL.md
├── data-analysis/
│ └── SKILL.md
└── writing-assistant/
└── SKILL.md
```
Users can clone and link:
```bash
git clone https://github.com/user/my-skills.git
ln -s my-skills/* ~/.picoclaw/skills/
```
## See Also
- [User Guide: Using Skills](../../user-guide/skills/using-skills.md)
- [User Guide: Creating Skills](../../user-guide/skills/creating-skills.md)
- [Skills Loader Source](https://github.com/sipeed/picoclaw/tree/main/pkg/skills)

View file

@ -0,0 +1,465 @@
# Creating Custom Tools
This guide explains how to create custom tools for PicoClaw.
## Overview
Tools are the primary way agents interact with the world. Each tool implements the `Tool` interface and can be invoked by the LLM during message processing.
## Tool Interface
All tools must implement this interface:
```go
type Tool interface {
Name() string
Description() string
Parameters() map[string]interface{}
Execute(ctx context.Context, args map[string]interface{}) *ToolResult
}
```
### Optional Interfaces
Tools can also implement optional interfaces for additional functionality:
```go
// ContextualTool receives channel/chat context
type ContextualTool interface {
Tool
SetContext(channel, chatID string)
}
// AsyncTool supports asynchronous execution
type AsyncTool interface {
Tool
SetCallback(cb AsyncCallback)
}
```
## Creating a Basic Tool
### Step 1: Define the Tool Struct
```go
package tools
import (
"context"
"fmt"
)
// CalculatorTool performs arithmetic operations
type CalculatorTool struct {
// Add any configuration fields here
}
func NewCalculatorTool() *CalculatorTool {
return &CalculatorTool{}
}
```
### Step 2: Implement Required Methods
```go
// Name returns the tool's identifier
func (t *CalculatorTool) Name() string {
return "calculator"
}
// Description explains what the tool does
func (t *CalculatorTool) Description() string {
return "Perform arithmetic calculations. Use this tool for mathematical operations."
}
// Parameters defines the JSON schema for arguments
func (t *CalculatorTool) Parameters() map[string]interface{} {
return map[string]interface{}{
"type": "object",
"properties": map[string]interface{}{
"operation": map[string]interface{}{
"type": "string",
"enum": []string{"add", "subtract", "multiply", "divide"},
"description": "The arithmetic operation to perform",
},
"a": map[string]interface{}{
"type": "number",
"description": "First operand",
},
"b": map[string]interface{}{
"type": "number",
"description": "Second operand",
},
},
"required": []string{"operation", "a", "b"},
}
}
```
### Step 3: Implement Execute
```go
// Execute performs the tool operation
func (t *CalculatorTool) Execute(ctx context.Context, args map[string]interface{}) *ToolResult {
// Extract arguments with type checking
operation, ok := args["operation"].(string)
if !ok {
return ErrorResult("operation must be a string")
}
a, ok := toFloat64(args["a"])
if !ok {
return ErrorResult("a must be a number")
}
b, ok := toFloat64(args["b"])
if !ok {
return ErrorResult("b must be a number")
}
// Perform calculation
var result float64
switch operation {
case "add":
result = a + b
case "subtract":
result = a - b
case "multiply":
result = a * b
case "divide":
if b == 0 {
return ErrorResult("division by zero")
}
result = a / b
default:
return ErrorResult(fmt.Sprintf("unknown operation: %s", operation))
}
// Return result
return UserResult(fmt.Sprintf("%.2f", result))
}
// Helper function to convert interface{} to float64
func toFloat64(v interface{}) (float64, bool) {
switch val := v.(type) {
case float64:
return val, true
case float32:
return float64(val), true
case int:
return float64(val), true
case int64:
return float64(val), true
default:
return 0, false
}
}
```
## Tool Results
PicoClaw provides several result types:
```go
// Basic result - content for LLM only
result := NewToolResult("Operation completed")
// Silent result - no user message, LLM only
result := SilentResult("File saved successfully")
// User result - same content for LLM and user
result := UserResult("Found 42 files")
// Error result
result := ErrorResult("Operation failed: reason")
// Async result
result := AsyncResult("Task started, will report back")
```
### Advanced Result Usage
```go
// Different content for LLM and user
result := &ToolResult{
ForLLM: "Technical details here...",
ForUser: "User-friendly summary here",
Silent: false,
}
// Error with underlying error
result := ErrorResult("Failed to connect").WithError(err)
```
## Contextual Tools
Tools that need channel/chat context implement `ContextualTool`:
```go
type NotificationTool struct {
defaultChannel string
defaultChatID string
}
func (t *NotificationTool) SetContext(channel, chatID string) {
t.defaultChannel = channel
t.defaultChatID = chatID
}
func (t *NotificationTool) Execute(ctx context.Context, args map[string]interface{}) *ToolResult {
// Use t.defaultChannel and t.defaultChatID
return UserResult(fmt.Sprintf("Notification sent to %s:%s", t.defaultChannel, t.defaultChatID))
}
```
## Async Tools
For long-running operations, implement `AsyncTool`:
```go
type LongRunningTool struct {
callback AsyncCallback
}
func (t *LongRunningTool) SetCallback(cb AsyncCallback) {
t.callback = cb
}
func (t *LongRunningTool) Execute(ctx context.Context, args map[string]interface{}) *ToolResult {
// Start async work
go func() {
// Do long-running work
time.Sleep(10 * time.Second)
result := UserResult("Long operation completed")
// Notify completion
if t.callback != nil {
t.callback(ctx, result)
}
}()
// Return immediately
return AsyncResult("Operation started, will complete in 10 seconds")
}
```
## Registering Tools
### Method 1: In AgentLoop
```go
// Register with all agents
agentLoop.RegisterTool(myTool)
```
### Method 2: In Tool Registry
```go
// Create registry
registry := tools.NewToolRegistry()
// Register tools
registry.Register(tools.NewCalculatorTool())
registry.Register(tools.NewMessageTool())
// Use in agent
agent.Tools = registry
```
## Complete Example: Database Query Tool
```go
package tools
import (
"context"
"database/sql"
"encoding/json"
"fmt"
_ "github.com/mattn/go-sqlite3"
)
type DatabaseTool struct {
db *sql.DB
}
func NewDatabaseTool(dbPath string) (*DatabaseTool, error) {
db, err := sql.Open("sqlite3", dbPath)
if err != nil {
return nil, err
}
return &DatabaseTool{db: db}, nil
}
func (t *DatabaseTool) Name() string {
return "database"
}
func (t *DatabaseTool) Description() string {
return "Execute SQL queries on the database. Use for data retrieval and analysis."
}
func (t *DatabaseTool) Parameters() map[string]interface{} {
return map[string]interface{}{
"type": "object",
"properties": map[string]interface{}{
"query": map[string]interface{}{
"type": "string",
"description": "SQL query to execute (SELECT only)",
},
},
"required": []string{"query"},
}
}
func (t *DatabaseTool) Execute(ctx context.Context, args map[string]interface{}) *ToolResult {
query, ok := args["query"].(string)
if !ok {
return ErrorResult("query must be a string")
}
// Security: Only allow SELECT queries
if !isSelectQuery(query) {
return ErrorResult("only SELECT queries are allowed")
}
// Execute query
rows, err := t.db.QueryContext(ctx, query)
if err != nil {
return ErrorResult(fmt.Sprintf("query failed: %v", err))
}
defer rows.Close()
// Get column names
columns, err := rows.Columns()
if err != nil {
return ErrorResult(fmt.Sprintf("failed to get columns: %v", err))
}
// Collect results
var results []map[string]interface{}
for rows.Next() {
values := make([]interface{}, len(columns))
valuePtrs := make([]interface{}, len(columns))
for i := range values {
valuePtrs[i] = &values[i]
}
if err := rows.Scan(valuePtrs...); err != nil {
return ErrorResult(fmt.Sprintf("scan failed: %v", err))
}
row := make(map[string]interface{})
for i, col := range columns {
row[col] = values[i]
}
results = append(results, row)
}
// Format result
jsonResult, _ := json.MarshalIndent(results, "", " ")
return UserResult(fmt.Sprintf("Found %d rows:\n%s", len(results), string(jsonResult)))
}
func isSelectQuery(query string) bool {
// Simple check - in production, use proper SQL parsing
return len(query) > 6 && query[:6] == "SELECT"
}
```
## Testing Tools
```go
package tools
import (
"context"
"testing"
)
func TestCalculatorTool(t *testing.T) {
tool := NewCalculatorTool()
// Test Name
if tool.Name() != "calculator" {
t.Errorf("expected name 'calculator', got %s", tool.Name())
}
// Test addition
result := tool.Execute(context.Background(), map[string]interface{}{
"operation": "add",
"a": 5,
"b": 3,
})
if result.IsError {
t.Errorf("unexpected error: %s", result.ForLLM)
}
if result.ForLLM != "8.00" {
t.Errorf("expected '8.00', got %s", result.ForLLM)
}
// Test division by zero
result = tool.Execute(context.Background(), map[string]interface{}{
"operation": "divide",
"a": 5,
"b": 0,
})
if !result.IsError {
t.Error("expected error for division by zero")
}
}
```
## Best Practices
1. **Clear Names**: Use descriptive, lowercase names with underscores
2. **Good Descriptions**: Explain what the tool does and when to use it
3. **Validate Inputs**: Check types and values before processing
4. **Meaningful Errors**: Return helpful error messages
5. **Security First**: Validate and sanitize all inputs
6. **Use Context**: Support cancellation for long operations
7. **Appropriate Results**: Choose the right result type
8. **Test Thoroughly**: Write tests for all scenarios
## Parameter Schema
The `Parameters()` method returns a JSON Schema object:
```go
func (t *MyTool) Parameters() map[string]interface{} {
return map[string]interface{}{
"type": "object",
"properties": map[string]interface{}{
"required_param": map[string]interface{}{
"type": "string",
"description": "Description of the parameter",
},
"optional_param": map[string]interface{}{
"type": "integer",
"description": "Optional parameter",
"default": 10,
},
"enum_param": map[string]interface{}{
"type": "string",
"enum": []string{"option1", "option2"},
"description": "Parameter with limited options",
},
"array_param": map[string]interface{}{
"type": "array",
"items": map[string]interface{}{"type": "string"},
"description": "Array of strings",
},
},
"required": []string{"required_param"},
}
}
```
## See Also
- [Tool Interface Reference](../api/tool-interface.md)
- [Tool Result Types](../api/tool-interface.md#toolresult)
- [Existing Tools](https://github.com/sipeed/picoclaw/tree/main/pkg/tools)

View file

@ -0,0 +1,400 @@
# Running Tests
This guide explains how to run and write tests for PicoClaw.
## Running Tests
### Run All Tests
Run the complete test suite:
```bash
make test
```
Or using Go directly:
```bash
go test ./pkg/...
```
### Run Tests for a Package
Test a specific package:
```bash
go test ./pkg/agent/... -v
go test ./pkg/providers/... -v
go test ./pkg/tools/... -v
```
### Run Specific Tests
Run tests matching a pattern:
```bash
go test ./pkg/providers/... -v -run TestFallbackChain
go test ./pkg/tools/... -v -run TestMessageTool
```
### Run with Verbose Output
```bash
go test ./pkg/... -v
```
### Run with Coverage
Generate coverage reports:
```bash
# Coverage for all packages
go test ./pkg/... -cover
# Detailed coverage report
go test ./pkg/... -coverprofile=coverage.out
go tool cover -html=coverage.out -o coverage.html
```
### Run Integration Tests
Integration tests require external APIs and are tagged separately:
```bash
go test ./pkg/... -v -tags=integration
```
Integration tests are located in files with the build tag:
```go
//go:build integration
// +build integration
```
## Test Organization
### Directory Structure
```
pkg/
├── agent/
│ ├── loop.go
│ ├── loop_test.go # Unit tests
│ └── loop_integration_test.go # Integration tests
├── providers/
│ ├── fallback.go
│ ├── fallback_test.go
│ └── openai_compat/
│ ├── provider.go
│ └── provider_test.go
└── tools/
├── message.go
├── message_test.go
└── ...
```
### Test File Naming
- Unit tests: `*_test.go`
- Integration tests: `*_integration_test.go` (with build tag)
## Writing Tests
### Basic Test
```go
package tools
import (
"context"
"testing"
)
func TestMessageTool(t *testing.T) {
tool := NewMessageTool()
// Test Name()
if tool.Name() != "message" {
t.Errorf("expected name 'message', got %s", tool.Name())
}
// Test Description()
if tool.Description() == "" {
t.Error("description should not be empty")
}
}
```
### Table-Driven Tests
```go
func TestToolResult(t *testing.T) {
tests := []struct {
name string
input string
expected string
isError bool
}{
{
name: "success",
input: "valid input",
expected: "valid input",
isError: false,
},
{
name: "error case",
input: "",
expected: "input is required",
isError: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := processInput(tt.input)
if result.ForLLM != tt.expected {
t.Errorf("expected %q, got %q", tt.expected, result.ForLLM)
}
if result.IsError != tt.isError {
t.Errorf("expected isError=%v, got %v", tt.isError, result.IsError)
}
})
}
}
```
### Testing Tool Execution
```go
func TestMessageToolExecute(t *testing.T) {
tool := NewMessageTool()
// Set up mock callback
var sentMessage string
tool.SetSendCallback(func(channel, chatID, content string) error {
sentMessage = content
return nil
})
// Set context
tool.SetContext("telegram", "123456")
// Execute
result := tool.Execute(context.Background(), map[string]interface{}{
"content": "Hello, world!",
})
// Verify
if result.IsError {
t.Errorf("unexpected error: %s", result.ForLLM)
}
if sentMessage != "Hello, world!" {
t.Errorf("expected 'Hello, world!', got %q", sentMessage)
}
}
```
### Testing with Context
```go
func TestWithContext(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond)
defer cancel()
result := longRunningOperation(ctx)
if result == nil {
t.Error("expected result")
}
}
```
### Testing Error Cases
```go
func TestErrorHandling(t *testing.T) {
tool := NewMessageTool()
// Execute without setting context
result := tool.Execute(context.Background(), map[string]interface{}{
"content": "Hello",
})
if !result.IsError {
t.Error("expected error when context not set")
}
}
```
### Mocking
Create mock implementations for testing:
```go
// Mock provider for testing
type MockProvider struct {
response *providers.LLMResponse
err error
}
func (m *MockProvider) Chat(ctx context.Context, messages []providers.Message,
tools []providers.ToolDefinition, model string,
options map[string]interface{}) (*providers.LLMResponse, error) {
return m.response, m.err
}
func (m *MockProvider) GetDefaultModel() string {
return "mock-model"
}
func TestWithMockProvider(t *testing.T) {
mock := &MockProvider{
response: &providers.LLMResponse{
Content: "Hello!",
},
}
// Use mock in tests
// ...
}
```
## Test Utilities
### Helper Functions
```go
// Create a test message bus
func newTestBus() *bus.MessageBus {
return bus.NewMessageBus()
}
// Create test config
func newTestConfig() *config.Config {
return &config.Config{
Agents: config.AgentsConfig{
Defaults: config.AgentDefaults{
Model: "test-model",
},
},
}
}
```
### Setup and Teardown
```go
func TestWithSetup(t *testing.T) {
// Setup
tmpDir, err := os.MkdirTemp("", "picoclaw-test")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(tmpDir) // Teardown
// Test using tmpDir
// ...
}
```
## Benchmark Tests
### Writing Benchmarks
```go
func BenchmarkToolExecute(b *testing.B) {
tool := NewMessageTool()
tool.SetContext("telegram", "123456")
tool.SetSendCallback(func(channel, chatID, content string) error {
return nil
})
args := map[string]interface{}{
"content": "test message",
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
tool.Execute(context.Background(), args)
}
}
```
### Running Benchmarks
```bash
go test ./pkg/tools/... -bench=.
go test ./pkg/tools/... -bench=. -benchmem
```
## Continuous Integration
Tests are run automatically in CI. Ensure all tests pass before submitting PRs:
```bash
# Run full check
make check
```
This runs:
1. `make deps` - Download dependencies
2. `make fmt` - Format code
3. `make vet` - Run linter
4. `make test` - Run tests
## Linting
Run the Go linter:
```bash
make vet
```
Or directly:
```bash
go vet ./pkg/...
```
## Common Issues
### Test Fails with "context deadline exceeded"
The test may be timing out. Increase the timeout or check for blocking operations:
```go
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
```
### Test Fails with "no such file or directory"
Tests may be looking for files in the wrong location. Use absolute paths or create temp directories:
```go
tmpDir := t.TempDir() // Automatically cleaned up
```
### Race Condition Detected
Run tests with race detection:
```bash
go test ./pkg/... -race
```
Fix race conditions by adding proper synchronization.
## Best Practices
1. **Write tests for new features** - Aim for good coverage
2. **Use table-driven tests** - Test multiple cases efficiently
3. **Test error paths** - Don't just test happy paths
4. **Use mocks for external dependencies** - Isolate unit tests
5. **Keep tests fast** - Use short timeouts and mock slow operations
6. **Clean up resources** - Use `t.Cleanup()` or defer
7. **Use meaningful test names** - Describe what's being tested
## Test Coverage Goals
- Aim for >70% coverage on core packages
- 100% coverage on critical paths (tool execution, message routing)
- Integration tests for end-to-end scenarios

View file

@ -0,0 +1,43 @@
# Getting Started
Welcome to PicoClaw! This section will help you get up and running quickly.
## Learning Path
1. **[Installation](installation.md)** - Install PicoClaw on your system
2. **[Quick Start](quick-start.md)** - Your first conversation in 5 minutes
3. **[Configuration Basics](configuration-basics.md)** - Understand the config structure
4. **[Your First Chat](first-chat.md)** - Interactive and one-shot messaging
## Prerequisites
Before you begin, you'll need:
- A computer running Linux, macOS, or Windows
- An API key from an LLM provider (OpenRouter, Zhipu, Anthropic, OpenAI, etc.)
## Quick Reference
```bash
# Install
picoclaw onboard
# Configure API key in ~/.picoclaw/config.json
# One-shot message
picoclaw agent -m "Hello!"
# Interactive mode
picoclaw agent
# Start gateway for chat apps
picoclaw gateway
```
## What's Next?
After completing the getting started guides:
- [User Guide](../user-guide/README.md) - Learn about all features
- [CLI Reference](../user-guide/cli-reference.md) - All command options
- [Configuration](../configuration/config-file.md) - Complete config reference

View file

@ -0,0 +1,147 @@
# Configuration Basics
This guide explains the fundamental concepts of PicoClaw configuration.
## Configuration File Location
PicoClaw stores its configuration in:
```
~/.picoclaw/config.json
```
Use `picoclaw onboard` to create a default configuration file.
## Configuration Sections
The configuration file has several main sections:
### agents
Controls agent behavior and model settings.
```json
{
"agents": {
"defaults": {
"workspace": "~/.picoclaw/workspace",
"model": "glm-4.7",
"max_tokens": 8192,
"temperature": 0.7
}
}
}
```
Key options:
- `workspace` - Where the agent stores files and sessions
- `model` - The LLM model to use
- `restrict_to_workspace` - Security sandbox (default: true)
### providers
API keys for LLM providers.
```json
{
"providers": {
"openrouter": {
"api_key": "sk-or-v1-xxx"
},
"zhipu": {
"api_key": "your-zhipu-key"
}
}
}
```
### channels
Chat platform integrations.
```json
{
"channels": {
"telegram": {
"enabled": true,
"token": "YOUR_BOT_TOKEN",
"allow_from": ["YOUR_USER_ID"]
}
}
}
```
### tools
Tool configuration.
```json
{
"tools": {
"web": {
"brave": {
"enabled": true,
"api_key": "YOUR_BRAVE_KEY"
}
}
}
}
```
## Environment Variables
All config options can be overridden with environment variables:
```bash
# Pattern: PICOCLAW_<SECTION>_<KEY>
export PICOCLAW_AGENTS_DEFAULTS_MODEL="gpt-4o"
export PICOCLAW_PROVIDERS_OPENROUTER_API_KEY="sk-or-v1-xxx"
```
## Provider Selection
PicoClaw selects providers in this order:
1. Explicit `provider` in config
2. Model name prefix (e.g., `openrouter/claude-...`)
3. First configured API key found
## Model Format
Models can be specified in two ways:
**With provider prefix:**
```json
{
"model": "openrouter/anthropic/claude-opus-4-5"
}
```
**Without prefix (uses default provider):**
```json
{
"model": "glm-4.7"
}
```
## Minimal Configuration
The minimal config to get started:
```json
{
"providers": {
"openrouter": {
"api_key": "sk-or-v1-xxx"
}
}
}
```
All other options have sensible defaults.
## Next Steps
- [Configuration Reference](../configuration/config-file.md) - All config options
- [Providers Guide](../user-guide/providers/README.md) - Provider setup details
- [Quick Start](quick-start.md) - Get running quickly

View file

@ -0,0 +1,118 @@
# Your First Chat
After [installing](installation.md) and [configuring](quick-start.md) PicoClaw, you're ready to chat!
## One-Shot Messages
Send a single message and get a response:
```bash
picoclaw agent -m "What is 2+2?"
```
The agent will process your message and print the response.
## Interactive Mode
Start an interactive chat session:
```bash
picoclaw agent
```
```
🦞 Interactive mode (Ctrl+C to exit)
🦞 You: Hello, who are you?
🦞 I'm PicoClaw, your AI assistant! I'm an ultra-lightweight AI agent written in Go. How can I help you today?
🦞 You: What can you do?
🦞 I can help you with many tasks:
- Answer questions and provide information
- Search the web for current information
- Read and write files in the workspace
- Execute shell commands
- Schedule reminders and tasks
- And much more!
```
### Interactive Commands
| Command | Action |
|---------|--------|
| Type a message | Send to the agent |
| `exit` or `quit` | Exit interactive mode |
| `Ctrl+C` | Exit interactive mode |
## Debug Mode
See what's happening behind the scenes:
```bash
picoclaw agent --debug -m "Hello"
```
Debug mode shows:
- LLM requests
- Tool calls
- Response processing
## Using Tools
The agent can use tools automatically. Just ask:
```bash
picoclaw agent -m "Search the web for the latest AI news and summarize it"
```
The agent will:
1. Use the `web_search` tool
2. Use the `web_fetch` tool to get content
3. Summarize the findings
## Sessions
Your conversation history is automatically saved. Continue a conversation:
```bash
# Start a session
picoclaw agent -s "project-planning" -m "I'm planning a new project"
# Continue later
picoclaw agent -s "project-planning" -m "What should we do next?"
```
Session files are stored in `~/.picoclaw/workspace/sessions/`.
## With Gateway
Connect to chat platforms:
```bash
# Start the gateway
picoclaw gateway
```
Then chat via:
- Telegram
- Discord
- Slack
- LINE
- And more
See [Channels](../user-guide/channels/README.md) for setup guides.
## Tips for Better Chats
1. **Be specific** - Clear questions get better answers
2. **Provide context** - Background info helps understanding
3. **Use sessions** - Maintain conversation context
4. **Check debug mode** - Understand what's happening
## Next Steps
- [CLI Reference](../user-guide/cli-reference.md) - All commands
- [Tools Overview](../user-guide/tools/README.md) - Available tools
- [Channels Guide](../user-guide/channels/README.md) - Connect to chat apps

View file

@ -0,0 +1,189 @@
# Installation
This guide covers installing PicoClaw on your system. Choose the method that best fits your needs.
## Quick Install
Download the precompiled binary for your platform from the [Releases page](https://github.com/sipeed/picoclaw/releases).
```bash
# Example: Download for Linux ARM64
wget https://github.com/sipeed/picoclaw/releases/download/v0.1.1/picoclaw-linux-arm64
chmod +x picoclaw-linux-arm64
./picoclaw-linux-arm64 onboard
```
## Installation Methods
### Option 1: Precompiled Binary (Recommended)
The easiest way to get started. Download the appropriate binary for your platform:
| Platform | Architecture | Binary Name |
|----------|-------------|-------------|
| Linux | x86_64 | `picoclaw-linux-amd64` |
| Linux | ARM64 | `picoclaw-linux-arm64` |
| Linux | RISC-V | `picoclaw-linux-riscv64` |
| Linux | LoongArch | `picoclaw-linux-loong64` |
| macOS | ARM64 (M1/M2/M3) | `picoclaw-darwin-arm64` |
| Windows | x86_64 | `picoclaw-windows-amd64.exe` |
```bash
# Download and make executable
wget https://github.com/sipeed/picoclaw/releases/latest/download/picoclaw-linux-amd64
chmod +x picoclaw-linux-amd64
# Move to PATH (optional)
sudo mv picoclaw-linux-amd64 /usr/local/bin/picoclaw
```
### Option 2: Build from Source
Building from source gives you the latest features and is recommended for development.
**Prerequisites:**
- Go 1.21 or later
- Git
**Steps:**
```bash
# Clone the repository
git clone https://github.com/sipeed/picoclaw.git
cd picoclaw
# Download dependencies
make deps
# Build for current platform
make build
# The binary will be in ./build/picoclaw
./build/picoclaw onboard
```
**Build for all platforms:**
```bash
make build-all
# Binaries will be in ./build/ for each platform
```
**Install to system:**
```bash
# Install to ~/.local/bin
make install
# Add to PATH (add to ~/.bashrc or ~/.zshrc)
export PATH="$HOME/.local/bin:$PATH"
```
### Option 3: Docker
Run PicoClaw in a container without installing anything locally.
```bash
# Clone the repository
git clone https://github.com/sipeed/picoclaw.git
cd picoclaw
# Configure
cp config/config.example.json config/config.json
# Edit config/config.json with your API keys
# Start gateway mode
docker compose --profile gateway up -d
# Or run agent mode (one-shot)
docker compose run --rm picoclaw-agent -m "Hello!"
# Interactive mode
docker compose run --rm picoclaw-agent
```
See [Docker Deployment](../deployment/docker.md) for more details.
### Option 4: Android/Termux
Run PicoClaw on old Android phones using Termux.
```bash
# Install Termux from F-Droid or Google Play
# Open Termux and run:
# Download binary
wget https://github.com/sipeed/picoclaw/releases/download/v0.1.1/picoclaw-linux-arm64
chmod +x picoclaw-linux-arm64
# Install proot for chroot environment
pkg install proot
# Initialize
termux-chroot ./picoclaw-linux-arm64 onboard
```
See [Termux Deployment](../deployment/termux.md) for more details.
## Verify Installation
After installing, verify PicoClaw is working:
```bash
# Check version
picoclaw version
# Check status
picoclaw status
```
## Next Steps
1. [Quick Start](quick-start.md) - Configure and run your first chat
2. [Configuration Basics](configuration-basics.md) - Understand the config structure
3. [Get API Keys](quick-start.md#get-api-keys) - Set up your LLM provider
## Supported Platforms
PicoClaw runs on a wide range of hardware:
| Hardware | Cost | Notes |
|----------|------|-------|
| Any Linux x86_64 | Varies | Most common |
| Raspberry Pi | $35+ | ARM64 support |
| LicheeRV Nano | $9.9 | RISC-V, ultra-low cost |
| MaixCAM | $50 | AI camera |
| NanoKVM | $30-100 | Server maintenance |
| Android phones | Free (old) | Via Termux |
| macOS | $500+ | M1/M2/M3 native |
## Troubleshooting
### Permission denied
```bash
chmod +x picoclaw-*
```
### Command not found
Make sure the binary is in your PATH:
```bash
# Add to PATH temporarily
export PATH="$PWD:$PATH"
# Or move to a standard location
sudo mv picoclaw-* /usr/local/bin/picoclaw
```
### Go version too old
PicoClaw requires Go 1.21 or later:
```bash
go version
# Upgrade Go if needed
```
### Docker issues
See [Docker Deployment](../deployment/docker.md) for troubleshooting Docker-specific issues.

View file

@ -0,0 +1,211 @@
# Quick Start
Get PicoClaw running in 5 minutes with this step-by-step guide.
## Prerequisites
- PicoClaw installed (see [Installation](installation.md))
- An API key from an LLM provider
## Step 1: Initialize
Run the onboard command to set up the default configuration:
```bash
picoclaw onboard
```
This creates:
- `~/.picoclaw/config.json` - Main configuration file
- `~/.picoclaw/workspace/` - Working directory for the agent
## Step 2: Get API Keys
You need at least one LLM provider API key.
### Recommended: OpenRouter
[OpenRouter](https://openrouter.ai/keys) provides access to many models with a free tier.
1. Go to [openrouter.ai/keys](https://openrouter.ai/keys)
2. Sign in and create an API key
3. Copy the key (starts with `sk-or-v1-`)
### Alternative: Zhipu (Chinese Users)
[Zhipu](https://open.bigmodel.cn/usercenter/proj-mgmt/apikeys) offers Chinese AI models.
1. Go to [bigmodel.cn](https://open.bigmodel.cn/usercenter/proj-mgmt/apikeys)
2. Register and create an API key
3. Copy the key
### Other Providers
| Provider | Get API Key | Notes |
|----------|-------------|-------|
| [Anthropic](https://console.anthropic.com) | Claude models | |
| [OpenAI](https://platform.openai.com) | GPT models | |
| [Gemini](https://aistudio.google.com) | Google models | Free tier available |
| [Groq](https://console.groq.com) | Fast inference | Free tier + voice transcription |
| [DeepSeek](https://platform.deepseek.com) | DeepSeek models | |
## Step 3: Configure
Edit `~/.picoclaw/config.json` and add your API key:
### Using OpenRouter
```json
{
"agents": {
"defaults": {
"workspace": "~/.picoclaw/workspace",
"model": "anthropic/claude-opus-4-5",
"max_tokens": 8192,
"temperature": 0.7,
"max_tool_iterations": 20
}
},
"providers": {
"openrouter": {
"api_key": "sk-or-v1-YOUR-API-KEY-HERE",
"api_base": "https://openrouter.ai/api/v1"
}
}
}
```
### Using Zhipu
```json
{
"agents": {
"defaults": {
"workspace": "~/.picoclaw/workspace",
"model": "glm-4.7",
"max_tokens": 8192,
"temperature": 0.7,
"max_tool_iterations": 20
}
},
"providers": {
"zhipu": {
"api_key": "YOUR-ZHIPU-API-KEY-HERE",
"api_base": "https://open.bigmodel.cn/api/paas/v4"
}
}
}
```
## Step 4: Chat
Now you're ready to chat with PicoClaw!
### One-shot Message
```bash
picoclaw agent -m "What is 2+2?"
```
### Interactive Mode
```bash
picoclaw agent
```
This starts an interactive chat session where you can have a continuous conversation.
### Debug Mode
For troubleshooting:
```bash
picoclaw agent --debug -m "Hello"
```
## Optional: Enable Web Search
PicoClaw can search the web. DuckDuckGo is enabled by default (no API key needed).
For better results, get a free [Brave Search API](https://brave.com/search/api) key (2000 queries/month):
```json
{
"tools": {
"web": {
"brave": {
"enabled": true,
"api_key": "YOUR_BRAVE_API_KEY",
"max_results": 5
},
"duckduckgo": {
"enabled": true,
"max_results": 5
}
}
}
}
```
## Optional: Connect to Chat Apps
To use PicoClaw with Telegram, Discord, or other chat platforms:
### Telegram
1. Create a bot via [@BotFather](https://t.me/BotFather)
2. Get your user ID from [@userinfobot](https://t.me/userinfobot)
3. Configure:
```json
{
"channels": {
"telegram": {
"enabled": true,
"token": "YOUR_BOT_TOKEN",
"allow_from": ["YOUR_USER_ID"]
}
}
}
```
4. Start the gateway:
```bash
picoclaw gateway
```
See [Telegram Setup](../user-guide/channels/telegram.md) for detailed instructions.
### Discord
See [Discord Setup](../user-guide/channels/discord.md) for detailed instructions.
## Next Steps
- [Configuration Basics](configuration-basics.md) - Learn about all config options
- [CLI Reference](../user-guide/cli-reference.md) - All commands and flags
- [Workspace Guide](../user-guide/workspace/structure.md) - Customize agent behavior
- [Tools Overview](../user-guide/tools/README.md) - Available tools
## Troubleshooting
### Web search shows "API configuration error"
This is normal without a Brave API key. DuckDuckGo fallback works automatically. To enable Brave search, add your API key to the config.
### Content filtering errors
Some providers have content filtering. Try:
- Rephrasing your query
- Using a different model
- Switching to a different provider
### Model not found
Make sure the model name is correct:
- OpenRouter: Use format like `anthropic/claude-opus-4-5`
- Zhipu: Use `glm-4.7`, `glm-4-plus`, etc.
- OpenAI: Use `gpt-4`, `gpt-4o`, etc.
See the [Troubleshooting Guide](../operations/troubleshooting.md) for more solutions.

View file

@ -0,0 +1,366 @@
# USB Device Monitoring
Monitor and manage USB devices connected to your PicoClaw system.
## Overview
PicoClaw can monitor USB devices for:
- Device connection/disconnection events
- Serial port availability
- Hardware health status
- Automated device-specific actions
## Use Cases
- **IoT deployments**: Monitor sensors and actuators
- **Edge devices**: Track connected hardware
- **Automation**: Trigger actions on device events
- **Debugging**: Track device issues in the field
## Device Detection
### List Connected Devices
Use the CLI to check connected devices:
```bash
picoclaw status --devices
```
### USB Device Events
PicoClaw can log USB device changes. Enable in configuration:
```json
{
"devices": {
"usb_monitor": {
"enabled": true,
"log_events": true,
"watch": [
{"vendor_id": "10c4", "product_id": "ea60"},
{"vendor_id": "0403", "product_id": "6001"}
]
}
}
}
```
## Serial Port Monitoring
### Configuration
```json
{
"devices": {
"serial": {
"enabled": true,
"ports": [
{
"path": "/dev/ttyUSB0",
"name": "sensor_node",
"baud_rate": 115200
},
{
"path": "/dev/ttyACM0",
"name": "arduino",
"baud_rate": 9600
}
]
}
}
}
```
### Serial Port Options
| Option | Type | Description |
|--------|------|-------------|
| `path` | string | Device path (e.g., `/dev/ttyUSB0`) |
| `name` | string | Friendly name for reference |
| `baud_rate` | int | Communication speed |
| `data_bits` | int | Data bits (default: 8) |
| `stop_bits` | int | Stop bits (default: 1) |
| `parity` | string | Parity: `none`, `even`, `odd` |
| `timeout` | int | Read timeout in seconds |
### Detecting Serial Ports
```bash
# List all serial ports
ls /dev/tty* | grep -E '(USB|ACM)'
# Using picocom to test
picocom -b 115200 /dev/ttyUSB0
# Using screen
screen /dev/ttyUSB0 115200
```
## Device Hotplug
### Linux udev Rules
Create udev rules for consistent device naming:
```bash
# /etc/udev/rules.d/99-picoclaw.rules
# USB serial device with specific vendor/product
SUBSYSTEM=="tty", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", SYMLINK+="picoclaw_sensor"
# Arduino boards
SUBSYSTEM=="tty", ATTRS{idVendor}=="2341", SYMLINK+="picoclaw_arduino"
# Set permissions
SUBSYSTEM=="tty", ATTRS{idVendor}=="10c4", MODE="0666"
```
Apply rules:
```bash
sudo udevadm control --reload-rules
sudo udevadm trigger
```
### Device Permissions
Add your user to required groups:
```bash
# For serial ports
sudo usermod -aG dialout $USER
# For USB devices
sudo usermod -aG plugdev $USER
# Logout and login for changes to take effect
```
## Hardware Health Monitoring
### System Sensors
Monitor system health with lm-sensors:
```bash
# Install lm-sensors
sudo apt install lm-sensors
# Detect sensors
sudo sensors-detect
# View readings
sensors
```
### Agent Integration
Configure PicoClaw to use hardware data:
```
User: "What's the system temperature?"
Agent uses exec tool to run `sensors` and reports:
"Current CPU temperature: 45.2°C"
```
### I2C Device Monitoring
Monitor I2C-connected sensors:
```json
{
"devices": {
"i2c": {
"enabled": true,
"bus": 1,
"devices": [
{
"address": "0x76",
"name": "bme280",
"type": "sensor",
"interval": "60s"
}
]
}
}
}
```
## USB Device Information
### Using lsusb
```bash
# List all USB devices
lsusb
# Verbose output for specific device
lsusb -v -d 10c4:ea60
# Show device tree
lsusb -t
```
### Using usb-devices
```bash
# Detailed device information
usb-devices
```
### Common USB Serial Chips
| Vendor ID | Product ID | Description |
|-----------|------------|-------------|
| `10c4` | `ea60` | CP210x (common USB-UART) |
| `0403` | `6001` | FTDI FT232 |
| `2341` | `0043` | Arduino Uno |
| `2341` | `0010` | Arduino Mega |
| `1a86` | `7523` | CH340 (cheap clones) |
## Troubleshooting
### Device Not Detected
1. Check physical connection
2. Verify driver is loaded:
```bash
lsmod | grep usbserial
```
3. Check dmesg for errors:
```bash
dmesg | grep -i usb
```
### Permission Denied
```bash
# Check device permissions
ls -la /dev/ttyUSB0
# Temporary fix
sudo chmod 666 /dev/ttyUSB0
# Permanent fix (add to dialout group)
sudo usermod -aG dialout $USER
```
### Device Disconnects Randomly
1. Check power supply (insufficient power can cause disconnects)
2. Check USB cable quality
3. Disable USB autosuspend:
```bash
echo -1 | sudo tee /sys/module/usbcore/parameters/autosuspend
```
### Multiple Same Devices
Use udev rules to create persistent symlinks based on serial number:
```bash
# Get device serial
udevadm info -a -n /dev/ttyUSB0 | grep serial
# Create symlink by serial
SUBSYSTEM=="tty", ATTRS{serial}=="12345", SYMLINK+="device_a"
```
## Monitoring Scripts
### Continuous Device Monitor
Create a monitoring script:
```bash
#!/bin/bash
# /usr/local/bin/usb-monitor.sh
while true; do
echo "=== $(date) ==="
lsusb
echo "Serial ports:"
ls -la /dev/tty* 2>/dev/null | grep -E '(USB|ACM)'
echo ""
sleep 60
done
```
### Alert on Device Disconnection
```bash
#!/bin/bash
# Alert when device disappears
DEVICE="/dev/ttyUSB0"
if [ ! -e "$DEVICE" ]; then
echo "ALERT: Device $DEVICE not found!"
# Send notification
# curl -X POST webhook_url -d "Device $DEVICE disconnected"
exit 1
fi
```
## Integration with PicoClaw
### Reading Sensor Data
```
User: "Read the temperature from the BME280 sensor"
Agent:
1. Uses i2c tool to detect devices
2. Reads from address 0x76
3. Parses sensor data
4. Returns: "Temperature: 23.5°C, Humidity: 65%, Pressure: 1013 hPa"
```
### Controlling Serial Devices
```
User: "Send the reset command to the Arduino"
Agent:
1. Uses exec tool: stty -F /dev/ttyACM0 9600
2. Echoes command: echo "RESET" > /dev/ttyACM0
3. Reads response: cat /dev/ttyACM0
4. Returns: "Arduino reset successfully"
```
### Automated Monitoring
Use cron tools for periodic checks:
```json
{
"cron": {
"jobs": [
{
"name": "check_sensors",
"schedule": "*/5 * * * *",
"prompt": "Check if all I2C sensors are responding and report any issues"
}
]
}
}
```
## Best Practices
1. **Use udev rules** for consistent device naming
2. **Monitor device health** with periodic checks
3. **Log device events** for troubleshooting
4. **Set up alerts** for critical devices
5. **Document device mappings** in your configuration
6. **Use quality cables** to prevent connection issues
7. **Consider power requirements** for USB devices
## See Also
- [Hardware Tools](../user-guide/tools/hardware.md)
- [I2C and SPI](../user-guide/tools/hardware.md)
- [Cron and Scheduled Tasks](../user-guide/tools/cron.md)
- [MaixCam Integration](../user-guide/channels/maixcam.md)

View file

@ -0,0 +1,283 @@
# Health Check Endpoints
PicoClaw provides health check endpoints for monitoring system status when running in gateway mode.
## Overview
Health endpoints allow you to monitor PicoClaw's operational status, which is essential for:
- Load balancer health checks
- Container orchestration (Kubernetes, Docker Swarm)
- Monitoring systems (Prometheus, Nagios)
- Automated alerting
## Endpoints
### Health Check
**Endpoint:** `GET /health`
Returns the overall health status of the PicoClaw gateway.
```bash
curl http://localhost:18790/health
```
**Response (Healthy):**
```json
{
"status": "healthy",
"timestamp": "2024-01-15T10:30:00Z",
"version": "1.0.0",
"uptime": "2h30m15s"
}
```
**Response (Unhealthy):**
```json
{
"status": "unhealthy",
"timestamp": "2024-01-15T10:30:00Z",
"version": "1.0.0",
"uptime": "2h30m15s",
"issues": [
"provider_connection_failed",
"redis_unavailable"
]
}
```
### Readiness Check
**Endpoint:** `GET /ready`
Returns whether PicoClaw is ready to accept requests.
```bash
curl http://localhost:18790/ready
```
**Response (Ready):**
```json
{
"ready": true,
"checks": {
"config_loaded": true,
"providers_initialized": true,
"channels_connected": true
}
}
```
**Response (Not Ready):**
```json
{
"ready": false,
"checks": {
"config_loaded": true,
"providers_initialized": false,
"channels_connected": false
}
}
```
### Liveness Check
**Endpoint:** `GET /live`
Simple endpoint to verify the process is running.
```bash
curl http://localhost:18790/live
```
**Response:**
```json
{
"alive": true
}
```
## Configuration
Configure health endpoints in your config file:
```json
{
"gateway": {
"port": 18790,
"health_check": {
"enabled": true,
"path": "/health",
"port": 18791
}
}
}
```
### Options
| Option | Default | Description |
|--------|---------|-------------|
| `enabled` | `true` | Enable health check endpoints |
| `path` | `/health` | Base path for health checks |
| `port` | Same as gateway | Separate port for health checks |
## Usage Examples
### Kubernetes Liveness Probe
```yaml
livenessProbe:
httpGet:
path: /live
port: 18790
initialDelaySeconds: 10
periodSeconds: 30
```
### Kubernetes Readiness Probe
```yaml
readinessProbe:
httpGet:
path: /ready
port: 18790
initialDelaySeconds: 5
periodSeconds: 10
```
### Docker Compose Health Check
```yaml
services:
picoclaw:
image: picoclaw:latest
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:18790/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
```
### Prometheus Blackbox Exporter
```yaml
modules:
http_2xx:
prober: http
http:
valid_status_codes: [200]
preferred_ip_protocol: ip4
```
```yaml
scrape_configs:
- job_name: 'picoclaw_health'
metrics_path: /probe
params:
module: [http_2xx]
targets:
- http://localhost:18790/health
```
### Load Balancer (nginx)
```nginx
upstream picoclaw {
server 127.0.0.1:18790;
}
server {
location /health {
proxy_pass http://picoclaw/health;
access_log off;
}
}
```
### HAProxy
```
backend picoclaw
option httpchk GET /health
http-check expect status 200
server picoclaw1 127.0.0.1:18790 check
```
## Status Codes
| Code | Meaning |
|------|---------|
| 200 | Healthy/Ready/Alive |
| 503 | Unhealthy/Not Ready |
## Detailed Status
For more detailed diagnostics, use the CLI status command:
```bash
picoclaw status
```
This provides comprehensive information about:
- All configured providers and their status
- Active channel connections
- Session statistics
- System resources
## Monitoring Integration
### Datadog
```yaml
# datadog.yaml
instances:
- url: http://localhost:18790/health
name: PicoClaw
tags:
- service:picoclaw
```
### New Relic
```yaml
# newrelic.yml
synthetics:
- name: PicoClaw Health
url: http://localhost:18790/health
verify_ssl: false
```
### Grafana + Prometheus
Use the blackbox exporter with Grafana dashboards for visual monitoring.
## Troubleshooting
### Endpoints not responding
1. Check gateway is running:
```bash
picoclaw gateway --debug
```
2. Verify port is accessible:
```bash
curl -v http://localhost:18790/health
```
3. Check firewall rules
### Returns 503 status
1. Check provider configuration
2. Verify API keys are valid
3. Check network connectivity to providers
## See Also
- [Monitoring Guide](monitoring.md)
- [Troubleshooting](troubleshooting.md)
- [Docker Deployment](../deployment/docker.md)

426
docs/operations/logging.md Normal file
View file

@ -0,0 +1,426 @@
# Log Management
This guide covers log configuration, collection, and analysis for PicoClaw.
## Overview
PicoClaw provides structured logging with multiple output formats and levels. Proper log management helps with:
- Debugging issues
- Security auditing
- Performance analysis
- Compliance requirements
## Log Levels
| Level | Description |
|-------|-------------|
| `debug` | Detailed debugging information |
| `info` | General operational messages |
| `warn` | Warning conditions |
| `error` | Error conditions |
## Configuration
### Basic Configuration
```json
{
"logging": {
"level": "info",
"format": "json",
"output": "stdout"
}
}
```
### Configuration Options
| Option | Default | Description |
|--------|---------|-------------|
| `level` | `info` | Minimum log level |
| `format` | `json` | Output format (`json`, `text`) |
| `output` | `stdout` | Output destination (`stdout`, `stderr`, file path) |
| `max_size` | `100` | Max log file size in MB (for file output) |
| `max_backups` | `3` | Max number of old log files |
| `max_age` | `28` | Max days to retain logs |
| `compress` | `true` | Compress rotated logs |
### Environment Variables
```bash
export PICOCLAW_LOGGING_LEVEL=debug
export PICOCLAW_LOGGING_FORMAT=json
export PICOCLAW_LOGGING_OUTPUT=/var/log/picoclaw/app.log
```
## Log Formats
### JSON Format (Recommended)
```json
{
"time": "2024-01-15T10:30:00.123Z",
"level": "info",
"component": "agent",
"message": "Processing message",
"session_id": "abc123",
"duration_ms": 1234,
"model": "claude-opus-4-5"
}
```
### Text Format
```
2024-01-15T10:30:00.123Z INFO agent Processing message session_id=abc123 duration_ms=1234
```
## Log Components
PicoClaw organizes logs by component:
| Component | Description |
|-----------|-------------|
| `main` | Application startup/shutdown |
| `config` | Configuration loading |
| `agent` | Agent loop and message processing |
| `provider` | LLM provider interactions |
| `channel` | Chat platform integrations |
| `tool` | Tool execution |
| `session` | Session management |
| `bus` | Message bus activity |
| `cron` | Scheduled tasks |
## Command Line Options
### Debug Mode
Enable verbose logging:
```bash
picoclaw agent --debug -m "Hello"
picoclaw gateway --debug
```
### Verbose Output
```bash
picoclaw agent -v -m "Hello"
picoclaw gateway -vv
```
| Flag | Level |
|------|-------|
| (none) | info |
| `-v` | info (verbose) |
| `-vv` | debug |
| `--debug` | debug (with stack traces) |
## File Logging
### Configuration
```json
{
"logging": {
"level": "info",
"format": "json",
"output": "/var/log/picoclaw/picoclaw.log",
"max_size": 100,
"max_backups": 5,
"max_age": 30,
"compress": true
}
}
```
### Directory Setup
```bash
# Create log directory
sudo mkdir -p /var/log/picoclaw
sudo chown $USER:$USER /var/log/picoclaw
```
### Log Rotation
PicoClaw handles log rotation automatically when configured for file output. Alternatively, use logrotate:
```bash
# /etc/logrotate.d/picoclaw
/var/log/picoclaw/*.log {
daily
missingok
rotate 7
compress
delaycompress
notifempty
create 0640 $USER $USER
sharedscripts
postrotate
systemctl reload picoclaw > /dev/null 2>&1 || true
endscript
}
```
## Log Collection
### Fluentd/Fluent Bit
```yaml
# fluent-bit.conf
[INPUT]
Name tail
Path /var/log/picoclaw/picoclaw.log
Tag picoclaw
[FILTER]
Name parser
Match picoclaw*
Key_Name log
Parser json
[OUTPUT]
Name elasticsearch
Match picoclaw*
Host elasticsearch
Port 9200
```
### Logstash
```ruby
# logstash.conf
input {
file {
path => "/var/log/picoclaw/picoclaw.log"
codec => json
type => "picoclaw"
}
}
filter {
if [type] == "picoclaw" {
date {
match => [ "time", "ISO8601" ]
}
}
}
output {
elasticsearch {
hosts => ["localhost:9200"]
index => "picoclaw-%{+YYYY.MM.dd}"
}
}
```
### Loki/Promtail
```yaml
# promtail.yml
scrape_configs:
- job_name: picoclaw
static_configs:
- targets:
- localhost
labels:
job: picoclaw
__path__: /var/log/picoclaw/*.log
pipeline_stages:
- json:
expressions:
level: level
component: component
message: message
- labels:
level:
component:
```
## Systemd Journal
When running as a systemd service, logs go to journald:
```bash
# View logs
journalctl -u picoclaw
# Follow logs
journalctl -u picoclaw -f
# Filter by level
journalctl -u picoclaw -p err
# Filter by time
journalctl -u picoclaw --since "1 hour ago"
```
### Journald Configuration
```bash
# /etc/systemd/journald.conf
[Journal]
Storage=persistent
Compress=yes
MaxRetentionSec=1month
```
## Docker Logging
### Default Configuration
```bash
docker run picoclaw:latest
```
Logs go to Docker's logging driver (json-file by default).
### Docker Compose
```yaml
services:
picoclaw:
image: picoclaw:latest
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
```
### Send to External System
```yaml
services:
picoclaw:
image: picoclaw:latest
logging:
driver: "syslog"
options:
syslog-address: "tcp://logserver:514"
syslog-facility: "daemon"
tag: "picoclaw"
```
## Log Analysis
### Common Queries
#### Error Count
```bash
grep -c '"level":"error"' /var/log/picoclaw/picoclaw.log
```
#### Recent Errors
```bash
grep '"level":"error"' /var/log/picoclaw/picoclaw.log | tail -20
```
#### Provider Errors
```bash
grep '"component":"provider"' /var/log/picoclaw/picoclaw.log | grep '"level":"error"'
```
#### Slow Requests
```bash
jq 'select(.duration_ms > 5000)' /var/log/picoclaw/picoclaw.log
```
### Using jq
```bash
# Parse and pretty print
cat picoclaw.log | jq '.'
# Filter by level
cat picoclaw.log | jq 'select(.level == "error")'
# Filter by component
cat picoclaw.log | jq 'select(.component == "agent")'
# Extract specific fields
cat picoclaw.log | jq '{time, level, message}'
# Count by level
cat picoclaw.log | jq -r '.level' | sort | uniq -c
```
## Security and Privacy
### Redacting Sensitive Data
PicoClaw automatically redacts:
- API keys (masked as `***`)
- Authentication tokens
- Passwords
### Manual Redaction
```bash
# Redact API keys before sharing logs
sed -E 's/sk-[a-zA-Z0-9]+/sk-***/g' picoclaw.log > redacted.log
```
### Log Access Control
```bash
# Restrict log file access
chmod 640 /var/log/picoclaw/picoclaw.log
chown root:picoclaw /var/log/picoclaw/picoclaw.log
```
## Debugging with Logs
### Enable Debug Mode
```json
{
"logging": {
"level": "debug"
}
}
```
### Trace a Session
```bash
# Find all logs for a session
grep '"session_id":"abc123"' /var/log/picoclaw/picoclaw.log
```
### Analyze Tool Calls
```bash
# All tool executions
grep '"component":"tool"' /var/log/picoclaw/picoclaw.log | jq '.'
```
### Provider Issues
```bash
# Provider connection issues
grep '"component":"provider"' /var/log/picoclaw/picoclaw.log | grep -E '(error|warn)'
```
## Best Practices
1. **Use JSON format** - Easier to parse and analyze
2. **Set appropriate levels** - Use `info` for production, `debug` for troubleshooting
3. **Configure rotation** - Prevent disk space issues
4. **Centralize logs** - Use a log aggregation system
5. **Monitor error rates** - Set up alerts for error spikes
6. **Secure logs** - Restrict access and redact sensitive data
7. **Archive old logs** - Keep historical data for analysis
## See Also
- [Monitoring Guide](monitoring.md)
- [Troubleshooting](troubleshooting.md)
- [Health Endpoints](health-endpoints.md)
- [Security Configuration](../deployment/security.md)

View file

@ -0,0 +1,351 @@
# Monitoring Setup Guide
This guide covers how to monitor PicoClaw in production environments.
## Overview
Effective monitoring helps you:
- Track system health and performance
- Detect issues before they impact users
- Understand usage patterns
- Plan capacity
## Monitoring Components
```
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ PicoClaw │───>│ Prometheus │───>│ Grafana │
│ Gateway │ │ (Metrics) │ │ (Dashboard) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
v
┌─────────────────┐ ┌─────────────────┐
│ Health │───>│ Alerting │
│ Endpoints │ │ System │
└─────────────────┘ └─────────────────┘
```
## Metrics Collection
### Prometheus Integration
PicoClaw exposes metrics in Prometheus format at `/metrics`:
```bash
curl http://localhost:18790/metrics
```
**Available Metrics:**
| Metric | Type | Description |
|--------|------|-------------|
| `picoclaw_messages_total` | Counter | Total messages processed |
| `picoclaw_messages_active` | Gauge | Currently active conversations |
| `picoclaw_tool_calls_total` | Counter | Tool invocations by type |
| `picoclaw_provider_requests_total` | Counter | Provider API requests |
| `picoclaw_provider_errors_total` | Counter | Provider API errors |
| `picoclaw_session_count` | Gauge | Active sessions |
| `picoclaw_response_time_seconds` | Histogram | Response latency |
### Prometheus Configuration
```yaml
# prometheus.yml
scrape_configs:
- job_name: 'picoclaw'
static_configs:
- targets: ['localhost:18790']
scrape_interval: 15s
metrics_path: /metrics
```
### Enable Metrics
Add to your configuration:
```json
{
"gateway": {
"metrics": {
"enabled": true,
"path": "/metrics"
}
}
}
```
## Grafana Dashboards
### Sample Dashboard Configuration
Import this dashboard configuration:
```json
{
"dashboard": {
"title": "PicoClaw Monitoring",
"panels": [
{
"title": "Messages per Minute",
"type": "graph",
"targets": [
{
"expr": "rate(picoclaw_messages_total[1m])",
"legendFormat": "Messages/min"
}
]
},
{
"title": "Response Time",
"type": "graph",
"targets": [
{
"expr": "histogram_quantile(0.95, rate(picoclaw_response_time_seconds_bucket[5m]))",
"legendFormat": "p95 Latency"
}
]
},
{
"title": "Provider Errors",
"type": "graph",
"targets": [
{
"expr": "rate(picoclaw_provider_errors_total[5m])",
"legendFormat": "{{provider}}"
}
]
},
{
"title": "Active Sessions",
"type": "stat",
"targets": [
{
"expr": "picoclaw_session_count",
"legendFormat": "Sessions"
}
]
}
]
}
}
```
## Alerting
### Prometheus Alert Rules
```yaml
# alerts.yml
groups:
- name: picoclaw
rules:
- alert: PicoClawDown
expr: up{job="picoclaw"} == 0
for: 1m
labels:
severity: critical
annotations:
summary: "PicoClaw is down"
description: "PicoClaw instance has been down for more than 1 minute."
- alert: HighErrorRate
expr: rate(picoclaw_provider_errors_total[5m]) > 0.1
for: 5m
labels:
severity: warning
annotations:
summary: "High provider error rate"
description: "Provider {{ $labels.provider }} has high error rate."
- alert: SlowResponses
expr: histogram_quantile(0.95, rate(picoclaw_response_time_seconds_bucket[5m])) > 30
for: 5m
labels:
severity: warning
annotations:
summary: "Slow response times"
description: "P95 response time exceeds 30 seconds."
- alert: HighMemoryUsage
expr: process_resident_memory_bytes{job="picoclaw"} > 52428800
for: 5m
labels:
severity: warning
annotations:
summary: "High memory usage"
description: "PicoClaw is using more than 50MB of memory."
```
### Alertmanager Configuration
```yaml
# alertmanager.yml
route:
receiver: 'team-notifications'
group_by: ['alertname', 'severity']
group_wait: 30s
group_interval: 5m
repeat_interval: 4h
receivers:
- name: 'team-notifications'
slack_configs:
- api_url: 'https://hooks.slack.com/services/xxx'
channel: '#alerts'
title: '{{ .GroupLabels.alertname }}'
text: '{{ .CommonAnnotations.description }}'
```
## Health Checks
### HTTP Health Monitoring
Use external services to monitor health endpoints:
```bash
# Simple health check
curl -f http://localhost:18790/health || exit 1
# Detailed health check with jq
curl -s http://localhost:18790/health | jq -r '.status' | grep -q "healthy" || exit 1
```
### Cron-based Monitoring
```bash
# /etc/cron.d/picoclaw-monitor
*/5 * * * * root curl -f http://localhost:18790/health || /usr/local/bin/alert-script.sh
```
## Log-based Monitoring
### Structured Logging
PicoClaw outputs structured logs that can be parsed:
```json
{
"time": "2024-01-15T10:30:00Z",
"level": "info",
"component": "agent",
"message": "Processing message",
"session_id": "abc123",
"duration_ms": 1234
}
```
### Log Aggregation
For Loki/Grafana stack:
```yaml
# loki/promtail.yml
clients:
- url: http://localhost:3100/loki/api/v1/push
scrape_configs:
- job_name: picoclaw
static_configs:
- targets:
- localhost
labels:
job: picoclaw
__path__: /var/log/picoclaw/*.log
```
## System Metrics
### Process Monitoring
Monitor PicoClaw process directly:
```bash
# CPU and memory usage
ps aux | grep picoclaw
# Open file descriptors
lsof -p $(pgrep picoclaw) | wc -l
# Network connections
netstat -an | grep 18790
```
### Resource Limits
Set appropriate limits:
```bash
# Systemd service with limits
[Service]
ExecStart=/usr/local/bin/picoclaw gateway
LimitNOFILE=65535
MemoryMax=100M
CPUQuota=50%
```
## Monitoring Checklist
### Basic Monitoring
- [ ] Health endpoint checks (every 30 seconds)
- [ ] Process uptime monitoring
- [ ] Log error rate monitoring
- [ ] API response time tracking
### Advanced Monitoring
- [ ] Provider latency and error rates
- [ ] Message throughput metrics
- [ ] Session count trends
- [ ] Memory usage over time
- [ ] Tool call success rates
### Alerting Setup
- [ ] Service down alerts
- [ ] High error rate alerts
- [ ] Slow response alerts
- [ ] Resource usage alerts
## Third-party Integrations
### Datadog
```yaml
# datadog.yaml
instances:
- url: http://localhost:18790/health
name: PicoClaw
tags:
- env:production
- service:picoclaw
collect_response_time: true
```
### New Relic
```yaml
# newrelic-infra.yml
integrations:
- name: nri-flex
config:
name: picoclawHealth
apis:
- name: health
url: http://localhost:18790/health
```
### Uptime Kuma
Add PicoClaw as a monitored service:
1. Create new monitor
2. URL: `http://your-server:18790/health`
3. Expected status: 200
## See Also
- [Health Endpoints](health-endpoints.md)
- [Logging Guide](logging.md)
- [Troubleshooting](troubleshooting.md)
- [Docker Deployment](../deployment/docker.md)

View file

@ -0,0 +1,426 @@
# Troubleshooting
This guide covers common issues and their solutions when using PicoClaw.
## Installation Issues
### Binary won't execute (Permission denied)
**Error:**
```
bash: ./picoclaw-*: Permission denied
```
**Solution:**
```bash
chmod +x picoclaw-*
```
### Command not found
**Error:**
```
bash: picoclaw: command not found
```
**Solution:**
Make sure the binary is in your PATH:
```bash
# Add current directory to PATH temporarily
export PATH="$PWD:$PATH"
# Or move to a standard location
sudo mv picoclaw-* /usr/local/bin/picoclaw
```
### Go version too old
**Error:**
```
go: cannot use Go 1.20, requires Go 1.21 or later
```
**Solution:**
```bash
# Check your Go version
go version
# Upgrade Go to 1.21 or later from https://go.dev/dl/
```
### Docker issues
**Error:**
```
Cannot connect to the Docker daemon
```
**Solution:**
Ensure Docker is running and you have permissions:
```bash
# Start Docker service
sudo systemctl start docker
# Add your user to docker group (requires logout/login)
sudo usermod -aG docker $USER
```
## Configuration Issues
### Config file not found
**Error:**
```
Error loading config: open ~/.picoclaw/config.json: no such file or directory
```
**Solution:**
Run the onboard command to create the default configuration:
```bash
picoclaw onboard
```
### Invalid JSON in config
**Error:**
```
Error loading config: invalid character '}' looking for beginning of value
```
**Solution:**
Validate your JSON syntax. Common issues:
- Missing commas between fields
- Trailing commas
- Unquoted strings
Use a JSON validator or:
```bash
cat ~/.picoclaw/config.json | python3 -m json.tool
```
## Provider Issues
### No API key configured
**Error:**
```
Error creating provider: no API key configured
```
**Solution:**
Add your API key to `~/.picoclaw/config.json`:
```json
{
"providers": {
"openrouter": {
"api_key": "sk-or-v1-xxx"
}
}
}
```
Or use environment variable:
```bash
export PICOCLAW_PROVIDERS_OPENROUTER_API_KEY="sk-or-v1-xxx"
```
### Model not found
**Error:**
```
Error: model 'xxx' not found
```
**Solution:**
Use the correct model name format:
- OpenRouter: `anthropic/claude-opus-4-5`, `openai/gpt-4o`
- Zhipu: `glm-4.7`, `glm-4-plus`
- OpenAI: `gpt-4`, `gpt-4o`
- Anthropic: `claude-opus-4-5`, `claude-sonnet-4`
### Rate limit exceeded
**Error:**
```
Error: rate limit exceeded
```
**Solution:**
1. Wait and retry
2. Set up fallback models:
```json
{
"agents": {
"defaults": {
"model": "primary-model",
"model_fallbacks": ["backup-model-1", "backup-model-2"]
}
}
}
```
### Content filtering errors
**Error:**
```
Error: content filtered
```
**Solution:**
Some providers have content filtering. Try:
1. Rephrasing your query
2. Using a different model
3. Switching to a different provider
## Channel Issues
### Telegram: Conflict error
**Error:**
```
Conflict: terminated by other getUpdates request
```
**Solution:**
Only one instance can use the bot token at a time:
1. Stop other running instances of the bot
2. Make sure only one `picoclaw gateway` is running
### Telegram: Bot not responding
**Possible causes:**
1. Bot not enabled:
```json
{
"channels": {
"telegram": {
"enabled": true
}
}
}
```
2. User not in allow list:
```json
{
"channels": {
"telegram": {
"allow_from": ["123456789"]
}
}
}
```
3. Gateway not running:
```bash
picoclaw gateway
```
### Discord: Missing intents
**Error:**
```
Bot requires MESSAGE CONTENT intent
```
**Solution:**
1. Go to [Discord Developer Portal](https://discord.com/developers/applications)
2. Select your application → Bot
3. Enable "MESSAGE CONTENT INTENT"
4. Save changes and restart gateway
### LINE: Webhook verification failed
**Error:**
```
Webhook verification failed
```
**Solution:**
1. Ensure webhook URL is accessible (use ngrok for testing)
2. Verify webhook path matches config
3. Check channel secret is correct
## Tool Issues
### Web search: API configuration error
**Error:**
```
Web search: API configuration error
```
**Solution:**
This is normal without a Brave API key. DuckDuckGo works automatically.
To enable Brave Search:
```json
{
"tools": {
"web": {
"brave": {
"enabled": true,
"api_key": "YOUR_BRAVE_API_KEY"
}
}
}
}
```
### Exec: Command blocked
**Error:**
```
Command blocked by safety guard (dangerous pattern detected)
```
**Solution:**
Some dangerous commands are always blocked for safety:
- `rm -rf`, `del /f`, `rmdir /s`
- `format`, `mkfs`, `diskpart`
- `dd if=`
- `shutdown`, `reboot`, `poweroff`
If you need to run restricted commands in a trusted environment:
```json
{
"agents": {
"defaults": {
"restrict_to_workspace": false
}
}
}
```
### Exec: Path outside working directory
**Error:**
```
Command blocked by safety guard (path outside working dir)
```
**Solution:**
The agent can only access files in the workspace. Either:
1. Move files into the workspace
2. Disable workspace restriction (security risk):
```bash
export PICOCLAW_AGENTS_DEFAULTS_RESTRICT_TO_WORKSPACE=false
```
## Session Issues
### Session history too large
**Symptom:**
Slow responses or memory issues.
**Solution:**
Sessions are automatically summarized when they exceed thresholds. You can also:
1. Delete old sessions: `rm ~/.picoclaw/workspace/sessions/*.json`
2. Start a new session: `picoclaw agent -s "new-session"`
### Session not persisting
**Solution:**
1. Check workspace directory exists: `ls ~/.picoclaw/workspace/sessions/`
2. Ensure write permissions: `chmod 755 ~/.picoclaw/workspace/sessions/`
## Performance Issues
### High memory usage
**Solution:**
1. Use a smaller model
2. Reduce `max_tokens`
3. Clear old sessions
4. Restart the gateway periodically
### Slow responses
**Possible causes:**
1. Large model - use a faster/smaller model
2. Network latency - use a provider closer to you
3. Rate limiting - set up fallback models
4. Complex tool calls - reduce tool iterations
### Gateway won't start
**Error:**
```
Error starting gateway: address already in use
```
**Solution:**
Change the gateway port:
```json
{
"gateway": {
"port": 18791
}
}
```
## Authentication Issues
### OAuth login failed
**Solution:**
1. Try device code flow for headless environments:
```bash
picoclaw auth login --provider openai --device-code
```
2. Check system clock is synchronized
### Token expired
**Error:**
```
Token has expired
```
**Solution:**
```bash
picoclaw auth login --provider openai
```
## Debug Mode
Enable debug logging for detailed output:
```bash
# Agent debug mode
picoclaw agent --debug -m "Hello"
# Gateway debug mode
picoclaw gateway --debug
```
Debug mode shows:
- LLM requests and responses
- Tool calls and results
- Message bus activity
- Configuration loading
## Getting Help
If you can't find a solution:
1. **GitHub Issues**: [Report a bug](https://github.com/sipeed/picoclaw/issues)
2. **GitHub Discussions**: [Ask a question](https://github.com/sipeed/picoclaw/discussions)
3. **Discord**: [Join our server](https://discord.gg/V4sAZ9XWpN)
When reporting issues, include:
- PicoClaw version (`picoclaw version`)
- Operating system and architecture
- Debug output (use `--debug`)
- Steps to reproduce
## Related Documentation
- [Configuration Reference](../configuration/config-file.md)
- [CLI Reference](../user-guide/cli-reference.md)
- [Quick Start](../getting-started/quick-start.md)

140
docs/tutorials/README.md Normal file
View file

@ -0,0 +1,140 @@
# Tutorials
Welcome to the PicoClaw tutorials. These step-by-step guides will help you get the most out of PicoClaw.
## Getting Started
If you're new to PicoClaw, start with the basic assistant tutorial.
| Tutorial | Difficulty | Time | Description |
|----------|------------|------|-------------|
| [Basic Assistant](basic-assistant.md) | Beginner | 10 min | Set up your first AI assistant |
| [Telegram Bot](telegram-bot.md) | Beginner | 15 min | Create a Telegram chatbot |
| [Scheduled Tasks](scheduled-tasks.md) | Intermediate | 15 min | Set up cron jobs and heartbeats |
| [Multi-Agent Setup](multi-agent-setup.md) | Intermediate | 20 min | Run multiple specialized agents |
| [Hardware Control](hardware-control.md) | Advanced | 25 min | Control I2C/SPI devices |
| [Skill Development](skill-development.md) | Advanced | 30 min | Create custom skills |
## Learning Path
### Beginner Path
```
Basic Assistant ──> Telegram Bot ──> Scheduled Tasks
```
1. **Basic Assistant**: Learn core concepts and CLI usage
2. **Telegram Bot**: Connect to a real chat platform
3. **Scheduled Tasks**: Automate periodic operations
### Intermediate Path
```
Multi-Agent Setup ──> Custom Configuration
```
4. **Multi-Agent Setup**: Run multiple agents with different purposes
5. Customize with your own configurations
### Advanced Path
```
Hardware Control ──> Skill Development
```
6. **Hardware Control**: Interface with physical devices
7. **Skill Development**: Extend PicoClaw with custom skills
## Tutorial Overview
### Basic Assistant Setup
Learn the fundamentals:
- Installing and configuring PicoClaw
- Setting up an LLM provider
- Your first conversation
- Understanding the workspace
[Start Tutorial](basic-assistant.md)
### Telegram Bot Tutorial
Build a Telegram chatbot:
- Creating a bot with BotFather
- Configuring the Telegram channel
- Testing your bot
- Adding custom commands
[Start Tutorial](telegram-bot.md)
### Scheduled Tasks Tutorial
Automate with scheduled tasks:
- Setting up cron jobs
- Configuring heartbeat tasks
- Using the HEARTBEAT.md file
- Monitoring scheduled tasks
[Start Tutorial](scheduled-tasks.md)
### Multi-Agent Tutorial
Run multiple agents:
- Understanding multi-agent architecture
- Configuring agent routing
- Setting up specialized agents
- Agent communication
[Start Tutorial](multi-agent-setup.md)
### Hardware Control Tutorial
Control hardware devices:
- Setting up I2C and SPI
- Reading sensor data
- Controlling actuators
- Building IoT applications
[Start Tutorial](hardware-control.md)
### Skill Development Tutorial
Create custom skills:
- Understanding the skill system
- Creating a basic skill
- Adding prompts and tools
- Testing and debugging
[Start Tutorial](skill-development.md)
## Prerequisites
Before starting tutorials, ensure you have:
- PicoClaw installed ([Installation Guide](../getting-started/installation.md))
- A provider API key (OpenRouter recommended)
- Basic command line knowledge
- A text editor for configuration files
## Getting Help
If you get stuck:
1. Check the [Troubleshooting Guide](../operations/troubleshooting.md)
2. Search [GitHub Issues](https://github.com/sipeed/picoclaw/issues)
3. Ask in [GitHub Discussions](https://github.com/sipeed/picoclaw/discussions)
4. Join our [Discord](https://discord.gg/V4sAZ9XWpN)
## Contributing Tutorials
Have a tutorial idea? We welcome contributions!
1. Check existing tutorials to avoid duplication
2. Follow the existing tutorial format
3. Include working code examples
4. Test your tutorial from scratch
5. Submit a pull request
## Next Steps
Ready to begin? Start with the [Basic Assistant Tutorial](basic-assistant.md).

View file

@ -0,0 +1,356 @@
# Basic Assistant Setup Tutorial
This tutorial guides you through setting up your first PicoClaw AI assistant.
## Prerequisites
- 10 minutes
- A computer running Linux, macOS, or Windows
- Internet connection
- An API key from an LLM provider
## Step 1: Install PicoClaw
### Download Binary (Recommended)
```bash
# Download the latest release for your platform
# Linux (amd64)
curl -LO https://github.com/sipeed/picoclaw/releases/latest/download/picoclaw-linux-amd64
# macOS (arm64)
curl -LO https://github.com/sipeed/picoclaw/releases/latest/download/picoclaw-darwin-arm64
# Windows (amd64)
curl -LO https://github.com/sipeed/picoclaw/releases/latest/download/picoclaw-windows-amd64.exe
```
### Make Executable
```bash
# Linux/macOS
chmod +x picoclaw-*
# Move to PATH (optional)
sudo mv picoclaw-* /usr/local/bin/picoclaw
```
### Verify Installation
```bash
picoclaw version
```
## Step 2: Get an API Key
### Recommended: OpenRouter
OpenRouter provides access to many models with a free tier (200K tokens/month).
1. Go to [openrouter.ai/keys](https://openrouter.ai/keys)
2. Sign in or create an account
3. Click "Create Key"
4. Copy your API key (starts with `sk-or-v1-`)
### Alternative Providers
| Provider | Sign Up | Free Tier |
|----------|---------|-----------|
| Zhipu | [bigmodel.cn](https://open.bigmodel.cn) | 200K tokens |
| Groq | [console.groq.com](https://console.groq.com) | Yes |
| Gemini | [aistudio.google.com](https://aistudio.google.com) | Yes |
## Step 3: Initialize Configuration
Run the onboard command to create default configuration:
```bash
picoclaw onboard
```
This creates:
- `~/.picoclaw/config.json` - Main configuration file
- `~/.picoclaw/workspace/` - Working directory
## Step 4: Add Your API Key
Edit the configuration file:
```bash
nano ~/.picoclaw/config.json
```
Add your OpenRouter API key:
```json
{
"agents": {
"defaults": {
"workspace": "~/.picoclaw/workspace",
"model": "anthropic/claude-opus-4-5",
"max_tokens": 8192,
"temperature": 0.7,
"max_tool_iterations": 20
}
},
"providers": {
"openrouter": {
"api_key": "sk-or-v1-YOUR-API-KEY-HERE",
"api_base": "https://openrouter.ai/api/v1"
}
}
}
```
Replace `YOUR-API-KEY-HERE` with your actual API key.
## Step 5: Your First Chat
### One-Shot Message
Send a single message:
```bash
picoclaw agent -m "Hello, what can you help me with?"
```
Expected output:
```
Hello! I'm your PicoClaw assistant. I can help you with:
- Answering questions and providing information
- Reading, writing, and managing files
- Running shell commands
- Searching the web
- And much more!
What would you like to do today?
```
### Interactive Mode
Start a continuous conversation:
```bash
picoclaw agent
```
```
> Hello!
Hello! How can I help you today?
> What is 2 + 2?
2 + 2 = 4
> Can you write that to a file?
[Uses write_file tool]
I've written "4" to result.txt in the workspace.
> Thanks!
You're welcome! Let me know if you need anything else.
> /exit
Goodbye!
```
## Step 6: Explore the Workspace
The workspace is where PicoClaw stores files and sessions:
```bash
# View workspace structure
ls -la ~/.picoclaw/workspace/
```
Output:
```
drwxr-xr-x sessions/ # Conversation history
drwxr-xr-x memory/ # Long-term memory
-rw-r--r-- AGENT.md # Agent behavior guide
-rw-r--r-- IDENTITY.md # Agent identity
```
### View Session History
```bash
ls ~/.picoclaw/workspace/sessions/
```
Sessions are stored as JSON files with your conversation history.
## Step 7: Customize Your Agent
### AGENT.md
The AGENT.md file defines how your agent behaves:
```bash
cat ~/.picoclaw/workspace/AGENT.md
```
Edit it to customize behavior:
```markdown
# Agent Behavior
You are a helpful AI assistant.
## Capabilities
- Answer questions
- Help with coding
- Manage files
## Personality
- Friendly and professional
- Clear and concise explanations
```
### IDENTITY.md
Define your agent's identity:
```markdown
# Identity
Name: PicoClaw Assistant
Version: 1.0
Created: 2024-01-15
I am an AI assistant powered by PicoClaw.
```
## Step 8: Enable Web Search (Optional)
PicoClaw can search the web. DuckDuckGo works without configuration.
For better results, add Brave Search:
1. Get a free API key from [brave.com/search/api](https://brave.com/search/api) (2000 queries/month)
2. Add to config:
```json
{
"tools": {
"web": {
"brave": {
"enabled": true,
"api_key": "YOUR_BRAVE_API_KEY",
"max_results": 5
},
"duckduckgo": {
"enabled": true,
"max_results": 5
}
}
}
}
```
## Step 9: Try Web Search
```bash
picoclaw agent -m "What's the latest news about AI?"
```
The agent will search the web and summarize relevant information.
## Understanding Tools
PicoClaw has built-in tools the agent can use:
| Tool | Description |
|------|-------------|
| `read_file` | Read file contents |
| `write_file` | Write to files |
| `list_files` | List directory contents |
| `exec` | Run shell commands |
| `web_search` | Search the web |
| `web_fetch` | Fetch web page content |
### Example: File Operations
```bash
picoclaw agent -m "Create a file called notes.txt with today's date"
```
The agent will:
1. Use `write_file` to create the file
2. Confirm the action
### Example: Shell Commands
```bash
picoclaw agent -m "What's the current system time?"
```
The agent will:
1. Use `exec` to run `date`
2. Report the time
## Debug Mode
When troubleshooting, use debug mode:
```bash
picoclaw agent --debug -m "Hello"
```
Debug mode shows:
- LLM requests and responses
- Tool calls and results
- Configuration details
## Common Issues
### "no API key configured"
Make sure your config file has the API key:
```bash
cat ~/.picoclaw/config.json | grep api_key
```
### "model not found"
Check the model name format:
- OpenRouter: `anthropic/claude-opus-4-5`
- Zhipu: `glm-4.7`
### "rate limit exceeded"
Wait a moment and try again, or set up fallback models:
```json
{
"agents": {
"defaults": {
"model": "anthropic/claude-opus-4-5",
"model_fallbacks": ["anthropic/claude-sonnet-4", "openai/gpt-4o"]
}
}
}
```
## Next Steps
Now that you have a basic assistant running, explore:
- [Telegram Bot Tutorial](telegram-bot.md) - Connect to Telegram
- [Scheduled Tasks Tutorial](scheduled-tasks.md) - Automate tasks
- [CLI Reference](../user-guide/cli-reference.md) - All commands
- [Tools Overview](../user-guide/tools/README.md) - Available tools
## Summary
You learned:
- How to install PicoClaw
- How to configure an LLM provider
- How to chat with the agent
- How to customize behavior
- How to enable web search
- Basic troubleshooting
Congratulations! You have a working AI assistant.

View file

@ -0,0 +1,500 @@
# Hardware Control Tutorial
This tutorial guides you through controlling I2C and SPI hardware devices with PicoClaw.
## Prerequisites
- 25 minutes
- Linux-based system (Raspberry Pi, SBC, etc.)
- PicoClaw installed and configured
- Basic electronics knowledge
- I2C or SPI devices to experiment with
## Overview
PicoClaw can interact with hardware devices through:
| Interface | Use Case | Speed |
|-----------|----------|-------|
| I2C | Sensors, displays, slow devices | 100-400 kHz |
| SPI | Flash memory, fast displays | Up to MHz |
## Part 1: Setup
### Enable I2C (Raspberry Pi)
```bash
# Using raspi-config
sudo raspi-config
# Interface Options -> I2C -> Yes
# Or manually
sudo apt install i2c-tools
sudo modprobe i2c-dev
```
### Enable SPI (Raspberry Pi)
```bash
# Using raspi-config
sudo raspi-config
# Interface Options -> SPI -> Yes
# Or manually
sudo modprobe spidev
```
### Set Permissions
```bash
# Add user to required groups
sudo usermod -aG i2c $USER
sudo usermod -aG spi $USER
# Logout and login for changes to take effect
```
### Verify Setup
```bash
# Check I2C buses
ls /dev/i2c-*
# Check SPI devices
ls /dev/spidev*
# Install tools
sudo apt install i2c-tools spi-tools
```
## Part 2: I2C Device Detection
### Scan for Devices
```bash
# Scan I2C bus 1
i2cdetect -y 1
```
Output:
```
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- 38 39 3a 3b 3c 3d 3e 3f
40: 40 41 42 43 44 45 46 47 -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- 6c -- -- --
70: -- -- -- -- -- -- -- 76
```
Numbers shown are device addresses in hex (e.g., 0x76, 0x38).
### Using PicoClaw
```
User: "Detect all I2C buses"
```
Agent response:
```
I'll detect the I2C buses on this system.
[Uses i2c tool with action "detect"]
Available I2C buses:
- i2c-1: Broadcom SMBus I2C adapter
User: "Scan bus 1 for devices"
[Uses i2c tool with action "scan", bus 1]
Found devices on bus 1:
- 0x38: Unknown device
- 0x40: Unknown device
- 0x76: Likely BME280/BMP280 sensor
```
## Part 3: Reading Sensor Data
### Example: BME280 Temperature Sensor
The BME280 is a popular temperature/humidity/pressure sensor at address 0x76 or 0x77.
```
User: "Read temperature from the BME280 at address 0x76"
```
Agent actions:
1. First, scan to verify device:
```json
{
"action": "scan",
"bus": 1
}
```
2. Read calibration data:
```json
{
"action": "read",
"bus": 1,
"address": "0x76",
"register": "0x88"
}
```
3. Read sensor registers:
```json
{
"action": "read",
"bus": 1,
"address": "0x76",
"register": "0xFA"
}
```
4. Calculate and report temperature.
### Example Conversation
```
User: What's the temperature reading?
Agent: I'll read the temperature from the BME280.
[Scans bus, finds device at 0x76]
[Reads register 0xFA for temperature data]
Current temperature: 23.5 degrees Celsius
Humidity: 65%
Pressure: 1013.25 hPa
User: Log this to a file
Agent: I'll append this reading to a log file.
[Writes to sensors.log]
Logged: 2024-01-15 10:30:00 - Temp: 23.5C, Humidity: 65%, Pressure: 1013.25hPa
```
## Part 4: SPI Communication
### List SPI Devices
```
User: "List available SPI devices"
```
Agent response:
```
[Uses spi tool with action "list"]
Available SPI devices:
- /dev/spidev0.0 (CS0)
- /dev/spidev0.1 (CS1)
```
### SPI Transfer
```
User: "Send bytes 0xAA 0xBB 0xCC to /dev/spidev0.0"
```
Agent action:
```json
{
"action": "transfer",
"device": "/dev/spidev0.0",
"data": "0xAA 0xBB 0xCC"
}
```
### Example: Read SPI Flash
```
User: "Read the first 16 bytes from the SPI flash on /dev/spidev0.0"
```
Agent actions:
1. Send read command (0x03) + address (0x00 0x00 0x00):
```json
{
"action": "transfer",
"device": "/dev/spidev0.0",
"data": "0x03 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00"
}
```
2. Parse the response and display hex dump.
## Part 5: Create a Hardware Agent
### Agent Configuration
Create a specialized hardware agent:
```bash
mkdir -p ~/.picoclaw/workspaces/hardware
nano ~/.picoclaw/workspaces/hardware/AGENT.md
```
```markdown
# Hardware Control Agent
## Role
You are a hardware controller for embedded and IoT devices.
## Capabilities
- I2C device detection and communication
- SPI device control
- Sensor reading and logging
- GPIO control (via exec tool)
## Known Devices
| Address | Device | Description |
|---------|--------|-------------|
| 0x76 | BME280 | Temp/Humidity/Pressure |
| 0x68 | DS1307/MPU6050 | RTC or IMU |
| 0x3C | SSD1306 | OLED Display |
| 0x27 | PCF8574 | I/O Expander |
## Behavior
1. Always detect devices before communication
2. Log all readings with timestamps
3. Handle errors gracefully
4. Report sensor values with units
## Safety
- Never write random values to unknown registers
- Verify device presence before operations
- Use appropriate delays between operations
```
### Add to Configuration
```json
{
"agents": {
"list": [
{
"id": "hardware",
"workspace": "~/.picoclaw/workspaces/hardware",
"model": "anthropic/claude-sonnet-4",
"restrict_to_workspace": false
}
]
}
}
```
### Use the Hardware Agent
```bash
picoclaw agent -a hardware -m "Scan all I2C buses and identify devices"
```
## Part 6: Practical Projects
### Project 1: Weather Station
Create a monitoring system:
```
User: "Set up a weather monitoring system"
Agent:
1. I'll configure a weather monitoring system using the BME280.
[Scans for device]
[Reads current values]
I'll create a logging script:
[Creates weather_log.sh using write_file]
Now let's set up a cron job to log every 5 minutes:
[Creates cron job using cron tool]
Weather station configured:
- Sensor: BME280 at 0x76
- Log file: ~/workspace/weather.log
- Interval: Every 5 minutes
```
### Project 2: OLED Display
Control an SSD1306 display:
```
User: "Display 'Hello World' on the OLED"
Agent:
I'll write to the SSD1306 display at 0x3C.
[Sends initialization sequence]
[Sends text data]
"Hello World" should now be displayed on the OLED.
```
### Project 3: Relay Control
Control relays via I2C I/O expander:
```
User: "Turn on relay 1"
Agent:
I'll control the relay via the PCF8574 at 0x27.
[Reads current state]
[Writes new state with bit 0 set]
Relay 1 is now ON.
```
## Part 7: Sensor Database
Create a sensor reading database:
### Using Heartbeat
Create `HEARTBEAT.md`:
```markdown
# Sensor Monitoring
Every 1 minute:
1. Read BME280 (temperature, humidity, pressure)
2. Read light sensor (if connected)
3. Append to ~/workspace/sensors.csv in format:
timestamp,temperature,humidity,pressure,light
4. Alert if any value is out of range
```
### Configure Heartbeat
```json
{
"heartbeat": {
"enabled": true,
"interval": "1m"
}
}
```
### Run
```bash
picoclaw agent --heartbeat
```
### Query Data
```
User: "What's the average temperature over the last hour?"
Agent:
[Reads sensors.csv]
[Calculates average]
Average temperature over the last hour: 23.2 degrees Celsius
Min: 22.8, Max: 24.1
```
## Part 8: Troubleshooting
### Device Not Detected
```bash
# Check I2C is enabled
ls /dev/i2c-*
# Check kernel modules
lsmod | grep i2c
# Check permissions
groups $USER
```
### Permission Denied
```bash
# Check device permissions
ls -la /dev/i2c-1
# Temporary fix
sudo chmod 666 /dev/i2c-1
# Permanent fix
sudo usermod -aG i2c $USER
# Logout and login
```
### Communication Errors
1. Check wiring (SDA, SCL, VCC, GND)
2. Verify pull-up resistors (4.7K typical)
3. Check device address
4. Try different bus speed
### PicoClaw Debug Mode
```bash
picoclaw agent --debug -a hardware -m "Read sensor"
```
## Common I2C Devices
| Device | Address | Type | Notes |
|--------|---------|------|-------|
| BME280 | 0x76/0x77 | Sensor | Temp/Humidity/Pressure |
| BMP280 | 0x76/0x77 | Sensor | Temp/Pressure only |
| MPU6050 | 0x68 | IMU | Accelerometer/Gyro |
| HMC5883L | 0x1E | Magnetometer | Compass |
| SSD1306 | 0x3C/0x3D | Display | 128x64 OLED |
| PCF8574 | 0x20-0x27 | I/O | 8-bit expander |
| DS1307 | 0x68 | RTC | Real-time clock |
| ADS1115 | 0x48-0x4B | ADC | 16-bit, 4 channels |
## Safety Guidelines
1. **Always verify device presence** before writing
2. **Check voltage levels** (3.3V vs 5V)
3. **Use pull-up resistors** for I2C
4. **Handle interrupts carefully**
5. **Log operations** for debugging
6. **Test commands manually** before automation
## Next Steps
- [Hardware Tools Reference](../user-guide/tools/hardware.md)
- [Multi-Agent Tutorial](multi-agent-setup.md) - Create a dedicated hardware agent
- [Scheduled Tasks](scheduled-tasks.md) - Automate sensor logging
- [MaixCam Integration](../user-guide/channels/maixcam.md) - Vision capabilities
## Summary
You learned:
- How to enable I2C and SPI interfaces
- How to detect and scan for devices
- How to read sensor data
- How to create a hardware agent
- Practical project examples
- Troubleshooting techniques
You can now control hardware devices with PicoClaw!

View file

@ -0,0 +1,537 @@
# Multi-Agent Setup Tutorial
This tutorial guides you through setting up multiple specialized agents with PicoClaw.
## Prerequisites
- 20 minutes
- PicoClaw installed and configured
- A working LLM provider
- Basic understanding of PicoClaw configuration
## Overview
Multi-agent setup allows you to run specialized agents for different tasks:
```
┌─────────────────────────────────────────────────────────────┐
│ PicoClaw │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Default │ │ Research │ │ Coding │ │ Hardware │ │
│ │ Agent │ │ Agent │ │ Agent │ │ Agent │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
│ ▲ ▲ ▲ ▲ │
│ │ │ │ │ │
│ ┌────┴────┐ ┌────┴────┐ ┌────┴────┐ ┌────┴────┐ │
│ │Telegram │ │Discord │ │ CLI │ │ CLI │ │
│ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │
└─────────────────────────────────────────────────────────────┘
```
## Use Cases
- **Specialized behavior**: Different agents for different tasks
- **Model optimization**: Use cheaper models for simple tasks
- **Access control**: Different permissions per channel
- **Workspace isolation**: Separate files and sessions
## Step 1: Understand Agent Configuration
### Default Agent
The default agent handles all unbound requests:
```json
{
"agents": {
"defaults": {
"workspace": "~/.picoclaw/workspace",
"model": "anthropic/claude-opus-4-5"
}
}
}
```
### Named Agents
Add agents to the `list` array:
```json
{
"agents": {
"defaults": { ... },
"list": [
{
"id": "research",
"workspace": "~/.picoclaw/workspaces/research",
"model": "anthropic/claude-opus-4-5"
}
]
}
}
```
## Step 2: Create Agent Workspaces
Each agent needs its own workspace:
```bash
# Create workspaces
mkdir -p ~/.picoclaw/workspaces/research
mkdir -p ~/.picoclaw/workspaces/coding
mkdir -p ~/.picoclaw/workspaces/hardware
```
## Step 3: Configure Multiple Agents
Edit `~/.picoclaw/config.json`:
```json
{
"agents": {
"defaults": {
"workspace": "~/.picoclaw/workspace",
"model": "anthropic/claude-opus-4-5",
"max_tokens": 8192,
"temperature": 0.7
},
"list": [
{
"id": "research",
"workspace": "~/.picoclaw/workspaces/research",
"model": "anthropic/claude-opus-4-5",
"temperature": 0.3,
"system_prompt": "You are a research assistant specialized in gathering and analyzing information."
},
{
"id": "coding",
"workspace": "~/.picoclaw/workspaces/coding",
"model": "anthropic/claude-sonnet-4",
"temperature": 0.2,
"system_prompt": "You are a coding assistant focused on writing clean, efficient code."
},
{
"id": "hardware",
"workspace": "~/.picoclaw/workspaces/hardware",
"model": "anthropic/claude-sonnet-4",
"restrict_to_workspace": false
}
]
}
}
```
## Step 4: Customize Agent Behavior
Create AGENT.md for each workspace:
### Research Agent
```bash
nano ~/.picoclaw/workspaces/research/AGENT.md
```
```markdown
# Research Agent
## Role
You are a research assistant specialized in gathering and analyzing information.
## Capabilities
- Web search and summarization
- Fact-checking and source verification
- Creating research summaries
- Organizing information
## Behavior
- Always cite sources
- Be thorough but concise
- Verify claims with multiple sources
- Store findings in memory
```
### Coding Agent
```bash
nano ~/.picoclaw/workspaces/coding/AGENT.md
```
```markdown
# Coding Agent
## Role
You are a coding assistant focused on writing clean, efficient code.
## Capabilities
- Writing code in various languages
- Code review and optimization
- Debugging and testing
- Documentation
## Behavior
- Follow best practices
- Include comments for complex logic
- Write testable code
- Explain your solutions
```
### Hardware Agent
```bash
nano ~/.picoclaw/workspaces/hardware/AGENT.md
```
```markdown
# Hardware Agent
## Role
You are a hardware controller for IoT and embedded systems.
## Capabilities
- I2C device communication
- SPI device control
- Sensor reading and logging
- Actuator control
## Behavior
- Always check device availability before operations
- Log all hardware interactions
- Handle errors gracefully
- Report sensor readings with units
```
## Step 5: Set Up Routing
Routing determines which agent handles which requests.
### Channel Binding
Bind specific channels to specific agents:
```json
{
"bindings": [
{
"channel": "telegram",
"chat_id": "123456789",
"agent_id": "default"
},
{
"channel": "discord",
"chat_id": "987654321",
"agent_id": "research"
}
]
}
```
### CLI Routing
Use the agent ID with CLI:
```bash
# Use default agent
picoclaw agent -m "Hello"
# Use specific agent
picoclaw agent --agent research -m "Research quantum computing"
picoclaw agent --agent coding -m "Write a Python script"
picoclaw agent --agent hardware -m "Read temperature sensor"
```
### Short form:
```bash
picoclaw agent -a research -m "Research topic"
```
## Step 6: Configure Subagents
Allow agents to spawn subagents for complex tasks:
```json
{
"agents": {
"defaults": {
"subagents": ["research", "coding", "hardware"]
},
"list": [
{
"id": "research",
"subagents": []
},
{
"id": "coding",
"subagents": ["research"]
},
{
"id": "hardware",
"subagents": []
}
]
}
}
```
### Using Subagents
The default agent can delegate to specialists:
```
User: "Research REST APIs and then create a Python client"
Agent: I'll research REST APIs first, then write the code.
[Spawns research agent]
Research complete: REST APIs are...
[Spawns coding agent]
Here's the Python client code...
```
## Step 7: Test Your Setup
### Test Each Agent
```bash
# Test default agent
picoclaw agent -m "Hello from default"
# Test research agent
picoclaw agent -a research -m "Research machine learning"
# Test coding agent
picoclaw agent -a coding -m "Write a hello world in Python"
# Test hardware agent
picoclaw agent -a hardware -m "List I2C devices"
```
### Verify Workspace Isolation
```bash
# Each agent has its own session
ls ~/.picoclaw/workspace/sessions/
ls ~/.picoclaw/workspaces/research/sessions/
ls ~/.picoclaw/workspaces/coding/sessions/
```
## Step 8: Model Optimization
Use different models for different agents:
```json
{
"agents": {
"list": [
{
"id": "simple",
"model": "openai/gpt-4o-mini",
"description": "Fast, cheap tasks"
},
{
"id": "complex",
"model": "anthropic/claude-opus-4-5",
"description": "Complex reasoning"
}
]
}
}
```
### Fallbacks Per Agent
```json
{
"agents": {
"list": [
{
"id": "research",
"model": "anthropic/claude-opus-4-5",
"model_fallbacks": [
"anthropic/claude-sonnet-4",
"openai/gpt-4o"
]
}
]
}
}
```
## Step 9: Advanced Routing Patterns
### Regex Routing
Route based on message patterns:
```json
{
"routing": {
"rules": [
{
"pattern": "^code:|^implement:|^debug:",
"agent_id": "coding"
},
{
"pattern": "^research:|^search:|^find:",
"agent_id": "research"
},
{
"pattern": "^sensor:|^i2c:|^hardware:",
"agent_id": "hardware"
}
]
}
}
```
### Time-Based Routing
Use different agents at different times:
```json
{
"routing": {
"rules": [
{
"time_range": {"start": "09:00", "end": "17:00"},
"agent_id": "work"
},
{
"time_range": {"start": "17:00", "end": "09:00"},
"agent_id": "personal"
}
]
}
}
```
## Step 10: Monitoring Multiple Agents
### Status Command
```bash
picoclaw status
```
Output:
```
PicoClaw Status
===============
Agents:
- default (anthropic/claude-opus-4-5)
Sessions: 5
- research (anthropic/claude-opus-4-5)
Sessions: 3
- coding (anthropic/claude-sonnet-4)
Sessions: 8
- hardware (anthropic/claude-sonnet-4)
Sessions: 2
Channels:
- telegram: connected
- discord: connected
```
## Practical Example: Dev Team Setup
Here's a complete configuration for a development team:
```json
{
"agents": {
"defaults": {
"workspace": "~/.picoclaw/workspace",
"model": "anthropic/claude-sonnet-4",
"max_tokens": 4096
},
"list": [
{
"id": "code-review",
"workspace": "~/.picoclaw/workspaces/code-review",
"model": "anthropic/claude-opus-4-5",
"system_prompt": "You are a code reviewer. Analyze code for bugs, security issues, and improvements."
},
{
"id": "docs",
"workspace": "~/.picoclaw/workspaces/docs",
"model": "anthropic/claude-sonnet-4",
"system_prompt": "You are a technical writer. Create clear, comprehensive documentation."
},
{
"id": "devops",
"workspace": "~/.picoclaw/workspaces/devops",
"model": "anthropic/claude-sonnet-4",
"system_prompt": "You are a DevOps engineer. Help with deployment, CI/CD, and infrastructure."
}
]
},
"bindings": [
{
"channel": "discord",
"chat_id": "code-review-channel-id",
"agent_id": "code-review"
},
{
"channel": "discord",
"chat_id": "docs-channel-id",
"agent_id": "docs"
}
]
}
```
## Troubleshooting
### Agent Not Found
```
Error: agent 'xyz' not found
```
Check the agent ID in your config matches what you're using.
### Wrong Agent Responding
1. Check bindings configuration
2. Verify routing rules
3. Check channel/chat IDs
### Workspace Issues
```
Error: workspace not accessible
```
1. Check workspace paths exist
2. Verify permissions
3. Check disk space
## Best Practices
1. **Use descriptive agent IDs** - Easy to remember and type
2. **Match models to tasks** - Use appropriate models for each agent
3. **Isolate workspaces** - Keep agent data separate
4. **Configure subagents wisely** - Only allow necessary delegation
5. **Monitor usage** - Track which agents are used most
6. **Document agents** - Clear AGENT.md for each
## Next Steps
- [Routing Documentation](../user-guide/advanced/routing.md) - Advanced routing
- [Spawn Tool](../user-guide/tools/spawn.md) - Subagent spawning
- [Session Management](../user-guide/advanced/session-management.md) - Session handling
## Summary
You learned:
- How to configure multiple agents
- How to create specialized agent workspaces
- How to set up channel bindings
- How to use subagents
- How to optimize models per agent
You can now run a multi-agent PicoClaw system!

View file

@ -0,0 +1,423 @@
# Scheduled Tasks Tutorial
This tutorial covers setting up automated tasks with cron jobs and heartbeat features.
## Prerequisites
- 15 minutes
- PicoClaw installed and configured
- A working LLM provider
## Overview
PicoClaw offers two ways to schedule automated tasks:
| Feature | Purpose | Trigger |
|---------|---------|---------|
| **Cron Jobs** | Specific scheduled tasks | Time-based (cron syntax) |
| **Heartbeat** | Periodic autonomous actions | Interval-based |
## Part 1: Cron Jobs
### Understanding Cron
Cron jobs run at specific times using cron syntax:
```
┌───────────── minute (0 - 59)
│ ┌───────────── hour (0 - 23)
│ │ ┌───────────── day of month (1 - 31)
│ │ │ ┌───────────── month (1 - 12)
│ │ │ │ ┌───────────── day of week (0 - 6) (Sunday = 0)
│ │ │ │ │
* * * * *
```
### Create a Cron Job
#### Using CLI
```bash
picoclaw cron add "0 9 * * *" "Send me a daily summary"
```
#### Using Configuration
Edit `~/.picoclaw/config.json`:
```json
{
"cron": {
"enabled": true,
"jobs": [
{
"name": "morning_summary",
"schedule": "0 9 * * *",
"prompt": "Generate a morning summary including the current date, weather, and any important notes from the memory file"
},
{
"name": "hourly_check",
"schedule": "0 * * * *",
"prompt": "Check system status and report any issues"
}
]
}
}
```
### Cron Schedule Examples
| Schedule | Meaning |
|----------|---------|
| `0 9 * * *` | Every day at 9:00 AM |
| `*/15 * * * *` | Every 15 minutes |
| `0 */2 * * *` | Every 2 hours |
| `0 9 * * 1` | Every Monday at 9:00 AM |
| `0 9 1 * *` | First day of every month |
| `0 0 * * *` | Every day at midnight |
### Managing Cron Jobs
#### List Jobs
```bash
picoclaw cron list
```
Output:
```
Name Schedule Next Run Prompt
---------------------------------------------------------------------------
morning_summary 0 9 * * * 2024-01-16 09:00:00 Generate a morning...
hourly_check 0 * * * * 2024-01-15 11:00:00 Check system status...
```
#### Remove Job
```bash
picoclaw cron remove morning_summary
```
#### Enable/Disable
```bash
picoclaw cron enable morning_summary
picoclaw cron disable morning_summary
```
### Cron with Output Channels
Send cron output to a channel:
```json
{
"cron": {
"enabled": true,
"jobs": [
{
"name": "daily_report",
"schedule": "0 18 * * *",
"prompt": "Generate a daily activity report",
"output": {
"channel": "telegram",
"chat_id": "123456789"
}
}
]
}
}
```
## Part 2: Heartbeat Tasks
### Understanding Heartbeat
Heartbeat tasks run at regular intervals, allowing the agent to act autonomously. They're defined in `HEARTBEAT.md`.
### Create HEARTBEAT.md
```bash
nano ~/.picoclaw/workspace/HEARTBEAT.md
```
```markdown
# Heartbeat Tasks
You are running in periodic mode. Every interval, perform these checks:
## System Health
- Check available disk space
- Check memory usage
- Report any anomalies
## Data Collection
- Collect sensor data (if hardware is connected)
- Update any tracking logs
## Notifications
- If any issues are found, prepare a notification
- Summarize findings concisely
## Memory Update
- Update MEMORY.md with important observations
```
### Configure Heartbeat
Edit `~/.picoclaw/config.json`:
```json
{
"heartbeat": {
"enabled": true,
"interval": "5m",
"max_runs": 0
}
}
```
### Configuration Options
| Option | Default | Description |
|--------|---------|-------------|
| `enabled` | `false` | Enable heartbeat tasks |
| `interval` | `5m` | Time between runs |
| `max_runs` | `0` | Maximum runs (0 = unlimited) |
### Interval Examples
| Interval | Meaning |
|----------|---------|
| `30s` | Every 30 seconds |
| `5m` | Every 5 minutes |
| `1h` | Every hour |
| `24h` | Every day |
### Running Heartbeat
```bash
# Start with heartbeat enabled
picoclaw agent --heartbeat
# Or with gateway
picoclaw gateway
```
### Environment Variable
```bash
export PICOCLAW_HEARTBEAT_ENABLED=true
export PICOCLAW_HEARTBEAT_INTERVAL=10m
picoclaw gateway
```
## Part 3: Practical Examples
### Example 1: Daily Backup Reminder
**Cron Job:**
```json
{
"cron": {
"jobs": [
{
"name": "backup_reminder",
"schedule": "0 20 * * *",
"prompt": "Check when the last backup was made (look in workspace/logs) and remind the user if it's been more than 24 hours"
}
]
}
}
```
### Example 2: System Monitoring
**Heartbeat (HEARTBEAT.md):**
```markdown
# System Monitor
Every 5 minutes, check:
1. CPU usage (use: top -bn1 | head -5)
2. Memory usage (use: free -h)
3. Disk space (use: df -h)
If any resource is above 80%, log a warning to ~/workspace/alerts.log
```
### Example 3: News Digest
**Cron Job:**
```json
{
"cron": {
"jobs": [
{
"name": "news_digest",
"schedule": "0 8 * * *",
"prompt": "Search for tech news from the last 24 hours and create a brief summary of the top 5 stories",
"output": {
"channel": "telegram",
"chat_id": "123456789"
}
}
]
}
}
```
### Example 4: Website Monitor
**Heartbeat:**
```markdown
# Website Monitor
Every 10 minutes:
1. Fetch https://example.com/health
2. If response is not 200, log to ~/workspace/outages.log
3. If this is a new outage, create an alert message
```
### Example 5: IoT Sensor Logger
**Heartbeat:**
```markdown
# Sensor Logger
Every minute:
1. Read temperature from I2C sensor at address 0x76
2. Read humidity
3. Append to ~/workspace/sensors.csv with timestamp
4. Alert if temperature > 30 or humidity > 80
```
## Part 4: Viewing Task History
### Cron Logs
```bash
picoclaw cron logs
```
Output:
```
Time Job Status Result
----------------------------------------------------------------
2024-01-15 09:00:00 morning_summary success Generated summary...
2024-01-15 10:00:00 hourly_check success System OK
2024-01-15 11:00:00 hourly_check success System OK
```
### Heartbeat Logs
Check the workspace logs:
```bash
cat ~/.picoclaw/workspace/heartbeat.log
```
## Part 5: Best Practices
### Use Appropriate Intervals
| Task Type | Recommended Interval |
|-----------|---------------------|
| Critical monitoring | 1-5 minutes |
| Regular checks | 5-15 minutes |
| Daily tasks | Once per day |
| Weekly summaries | Once per week |
### Error Handling
Include error handling in your prompts:
```markdown
When performing tasks:
- If an operation fails, log the error
- Try up to 3 times before giving up
- Report failures clearly
```
### Resource Management
Avoid resource-intensive tasks:
```markdown
Guidelines:
- Keep operations quick (< 30 seconds)
- Don't create large files
- Clean up temporary data
- Use efficient commands
```
### Idempotency
Make tasks idempotent (safe to run multiple times):
```markdown
Before performing actions:
- Check if action is needed
- Don't duplicate work
- Update timestamps, don't create new entries
```
## Troubleshooting
### Cron Jobs Not Running
1. Check cron is enabled:
```json
{"cron": {"enabled": true}}
```
2. Verify schedule syntax:
```bash
# Test cron expression
crontab -e
# Add: * * * * * echo "test" >> /tmp/cron-test
```
3. Check gateway is running
### Heartbeat Not Working
1. Check heartbeat is enabled:
```bash
picoclaw agent --debug --heartbeat
```
2. Verify HEARTBEAT.md exists:
```bash
cat ~/.picoclaw/workspace/HEARTBEAT.md
```
3. Check interval is reasonable
### Tasks Taking Too Long
1. Reduce task complexity
2. Increase interval
3. Use simpler prompts
## Next Steps
- [Multi-Agent Tutorial](multi-agent-setup.md) - Run specialized agents
- [Cron Tool Docs](../user-guide/tools/cron.md) - Full cron documentation
- [Heartbeat Docs](../user-guide/workspace/heartbeat-tasks.md) - Heartbeat details
## Summary
You learned:
- How to create and manage cron jobs
- How to configure heartbeat tasks
- Practical scheduling examples
- Best practices for automated tasks
You can now automate your PicoClaw assistant!

View file

@ -0,0 +1,512 @@
# Skill Development Tutorial
This tutorial guides you through creating custom skills for PicoClaw.
## Prerequisites
- 30 minutes
- PicoClaw installed and configured
- Basic understanding of PicoClaw tools
- Text editor for creating files
## Overview
Skills are reusable packages that extend PicoClaw capabilities:
```
┌─────────────────────────────────────────┐
│ Skill │
├─────────────────────────────────────────┤
│ skill.md - Behavior prompts │
│ tools.json - Custom tool definitions │
│ templates/ - File templates │
│ examples/ - Usage examples │
└─────────────────────────────────────────┘
```
## Part 1: Understanding Skills
### What Skills Can Do
- Define specialized behavior prompts
- Provide domain-specific knowledge
- Include templates and examples
- Configure tool usage
### Skill Location
Skills are stored in the workspace:
```
~/.picoclaw/workspace/skills/
├── built-in/ # System skills
├── custom/ # Your custom skills
└── installed/ # Installed from external sources
```
## Part 2: Create Your First Skill
### Example: Meeting Notes Skill
Create a skill for managing meeting notes.
#### Create Skill Directory
```bash
mkdir -p ~/.picoclaw/workspace/skills/meeting-notes
cd ~/.picoclaw/workspace/skills/meeting-notes
```
#### Create skill.md
```bash
nano skill.md
```
```markdown
# Meeting Notes Skill
## Purpose
Help users capture, organize, and search meeting notes.
## Behavior
When helping with meeting notes:
1. Use consistent formatting
2. Extract action items automatically
3. Identify attendees and decisions
4. Store notes with timestamps
## Note Format
```markdown
# Meeting: [Title]
Date: [Date]
Attendees: [List]
## Agenda
- [Item 1]
- [Item 2]
## Discussion
[Key points]
## Decisions
- [Decision 1]
- [Decision 2]
## Action Items
- [ ] [Task] - [Owner] - [Due Date]
```
## Commands
- "New meeting note" - Create a new note
- "Add action item" - Add to current meeting
- "List meetings" - Show recent meetings
- "Search notes" - Search through all notes
```
#### Test the Skill
```bash
picoclaw agent -m "Use the meeting-notes skill to create a new meeting note about project planning"
```
## Part 3: Add Custom Tools
### Create tools.json
Some skills benefit from custom tool definitions:
```bash
nano tools.json
```
```json
{
"tools": [
{
"name": "create_meeting",
"description": "Create a new meeting note file",
"parameters": {
"type": "object",
"properties": {
"title": {
"type": "string",
"description": "Meeting title"
},
"attendees": {
"type": "array",
"items": {"type": "string"},
"description": "List of attendee names"
},
"date": {
"type": "string",
"description": "Meeting date (YYYY-MM-DD)"
}
},
"required": ["title"]
},
"implementation": {
"type": "write_file",
"path_template": "meetings/{{date}}-{{slugify title}}.md",
"content_template": "# Meeting: {{title}}\nDate: {{date}}\nAttendees: {{join attendees ', '}}\n\n## Agenda\n\n## Discussion\n\n## Decisions\n\n## Action Items\n"
}
}
]
}
```
## Part 4: Add Templates
### Create Templates Directory
```bash
mkdir -p templates
nano templates/meeting.md
```
```markdown
# Meeting: {{title}}
Date: {{date}}
Time: {{time}}
Attendees: {{attendees}}
## Agenda
{{#each agenda_items}}
- {{this}}
{{/each}}
## Discussion
{{discussion}}
## Decisions
{{#each decisions}}
- {{this}}
{{/each}}
## Action Items
{{#each action_items}}
- [ ] {{this.task}} - {{this.owner}} - {{this.due}}
{{/each}}
---
Created with PicoClaw Meeting Notes Skill
```
## Part 5: Add Examples
### Create Examples
```bash
mkdir -p examples
nano examples/basic-usage.md
```
```markdown
# Meeting Notes Examples
## Example 1: Create a Meeting Note
User: "Create a meeting note for today's standup with Alice, Bob, and Carol"
Agent creates: meetings/2024-01-15-standup.md
## Example 2: Add Action Items
User: "Add action item: Bob will finish the API by Friday"
Agent appends to current meeting:
- [ ] Finish the API - Bob - Friday
## Example 3: Search Notes
User: "Search meeting notes for 'budget'"
Agent searches all meeting files and returns matches.
```
## Part 6: Skill Manifest
Create a manifest for sharing:
```bash
nano skill.json
```
```json
{
"name": "meeting-notes",
"version": "1.0.0",
"description": "Capture and organize meeting notes",
"author": "Your Name",
"tags": ["productivity", "notes", "meetings"],
"min_picoclaw_version": "1.0.0",
"files": [
"skill.md",
"tools.json",
"templates/meeting.md",
"examples/basic-usage.md"
]
}
```
## Part 7: More Skill Examples
### Example: Code Review Skill
```markdown
# Code Review Skill
## Purpose
Provide thorough code reviews with actionable feedback.
## Review Checklist
1. **Functionality**: Does the code do what it's supposed to?
2. **Readability**: Is the code easy to understand?
3. **Performance**: Are there obvious bottlenecks?
4. **Security**: Are there potential vulnerabilities?
5. **Testing**: Is there adequate test coverage?
## Output Format
```markdown
## Code Review
### Summary
[Brief overall impression]
### Strengths
- [What's done well]
### Issues
#### Critical
- [Must fix]
#### Suggestions
- [Nice to have]
### Questions
- [Clarification needed]
```
## Commands
- "Review this code: [paste code]"
- "Review file [path]"
- "Check for security issues in [path]"
```
### Example: Documentation Skill
```markdown
# Documentation Skill
## Purpose
Generate and maintain technical documentation.
## Capabilities
- Generate API documentation
- Create README files
- Write user guides
- Document code comments
## Documentation Style
- Clear and concise
- Include code examples
- Use proper markdown formatting
- Add diagrams where helpful
## Templates Available
- README.md
- API_REFERENCE.md
- CONTRIBUTING.md
- CHANGELOG.md
```
### Example: DevOps Skill
```markdown
# DevOps Skill
## Purpose
Help with deployment, CI/CD, and infrastructure.
## Capabilities
- Docker configuration
- CI/CD pipeline setup
- Kubernetes manifests
- Infrastructure as code
## Best Practices
- Use version control
- Implement proper logging
- Set up monitoring
- Configure alerts
- Use secrets management
## Common Tasks
- "Create a Dockerfile for [app]"
- "Set up GitHub Actions for [project]"
- "Create Kubernetes deployment for [service]"
```
## Part 8: Using Skills
### List Available Skills
```bash
picoclaw skills list
```
### Use a Skill
```bash
# In conversation
picoclaw agent -m "Use the meeting-notes skill to create a note"
# Or load skill explicitly
picoclaw agent --skill meeting-notes -m "Create a new meeting note"
```
### Skill Auto-Loading
Skills in the workspace are automatically available:
```
User: "Create a meeting note for my standup"
Agent recognizes the meeting-notes skill context and uses it.
```
## Part 9: Sharing Skills
### Package for Distribution
```bash
# Create archive
cd ~/.picoclaw/workspace/skills
tar -czvf meeting-notes-skill.tar.gz meeting-notes/
```
### Install from Archive
```bash
picoclaw skills install meeting-notes-skill.tar.gz
```
### Install from URL
```bash
picoclaw skills install https://example.com/skills/meeting-notes.tar.gz
```
### Install from GitHub
```bash
picoclaw skills install github:user/picoclaw-skills/meeting-notes
```
## Part 10: Testing Skills
### Manual Testing
```bash
# Test basic functionality
picoclaw agent -m "Use meeting-notes to create a test meeting"
# Verify file creation
ls ~/.picoclaw/workspace/meetings/
# Test edge cases
picoclaw agent -m "Create a meeting note with no attendees"
```
### Debug Mode
```bash
picoclaw agent --debug -m "Use meeting-notes skill"
```
## Best Practices
### 1. Clear Purpose
Each skill should have one clear purpose:
```
Good: "Create and manage meeting notes"
Bad: "Handle meetings, emails, and documents"
```
### 2. Specific Instructions
Give explicit instructions in skill.md:
```markdown
## Behavior
1. Always ask for missing required fields
2. Use ISO date format (YYYY-MM-DD)
3. Create backups before modifying
```
### 3. Error Handling
Include error handling guidance:
```markdown
## Error Handling
- If file exists, prompt to overwrite or append
- If template is missing, use default format
- If date is invalid, use current date
```
### 4. Examples
Provide usage examples:
```markdown
## Examples
### Creating a Meeting
User: "New meeting: Project kickoff with John and Jane"
Creates: meetings/2024-01-15-project-kickoff.md
### Adding Actions
User: "Add action: John to prepare slides by Wednesday"
Appends action item to current meeting
```
## Troubleshooting
### Skill Not Loading
1. Check file permissions
2. Verify skill.md syntax
3. Check workspace path
### Unexpected Behavior
1. Review skill.md instructions
2. Check for conflicts with other skills
3. Use debug mode
### Tools Not Working
1. Verify tools.json syntax
2. Check parameter definitions
3. Test tool calls in debug mode
## Next Steps
- [Skills Documentation](../user-guide/skills/README.md)
- [Built-in Skills](../user-guide/skills/builtin-skills.md)
- [Creating Skills Guide](../user-guide/skills/creating-skills.md)
## Summary
You learned:
- What skills are and how they work
- How to create skill.md behavior files
- How to add custom tools
- How to use templates
- How to package and share skills
- Best practices for skill development
You can now extend PicoClaw with custom skills!

View file

@ -0,0 +1,436 @@
# Telegram Bot Tutorial
This tutorial guides you through creating a Telegram chatbot with PicoClaw.
## Prerequisites
- 15 minutes
- PicoClaw installed and configured
- A Telegram account
- A configured LLM provider (see [Basic Assistant](basic-assistant.md))
## Step 1: Create a Telegram Bot
### Talk to BotFather
1. Open Telegram
2. Search for `@BotFather`
3. Start a conversation
### Create New Bot
Send `/newbot` to BotFather:
```
You: /newbot
BotFather: Alright, a new bot. How are we going to call it?
Please choose a name for your bot.
You: My PicoClaw Assistant
BotFather: Good. Now let's choose a username for your bot.
It must end in `bot`. Like this, for example: TetrisBot or tetris_bot.
You: my_picoclaw_assistant_bot
BotFather: Done! Congratulations on your new bot...
Use this token to access the HTTP API:
7123456789:AAHxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Keep your token secure...
```
### Save the Token
Copy and save the bot token (the long string starting with numbers). You'll need it for configuration.
## Step 2: Get Your User ID
### Use userinfobot
1. Search for `@userinfobot`
2. Start a conversation
3. It will reply with your user ID
```
You: /start
UserInfoBot: Your user ID: 123456789
```
Save this ID for the allow list.
## Step 3: Configure PicoClaw
### Edit Configuration
```bash
nano ~/.picoclaw/config.json
```
Add Telegram channel configuration:
```json
{
"agents": {
"defaults": {
"workspace": "~/.picoclaw/workspace",
"model": "anthropic/claude-opus-4-5"
}
},
"providers": {
"openrouter": {
"api_key": "sk-or-v1-xxx"
}
},
"channels": {
"telegram": {
"enabled": true,
"token": "7123456789:AAHxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"allow_from": [123456789]
}
}
}
```
Replace:
- `7123456789:AAH...` with your bot token
- `123456789` with your user ID
### Configuration Options
| Option | Required | Description |
|--------|----------|-------------|
| `enabled` | Yes | Enable the channel |
| `token` | Yes | Bot token from BotFather |
| `allow_from` | Recommended | List of allowed user IDs |
## Step 4: Start the Gateway
The gateway connects PicoClaw to Telegram:
```bash
picoclaw gateway
```
Output:
```
2024-01-15T10:30:00Z INFO main Starting PicoClaw gateway...
2024-01-15T10:30:00Z INFO channel Connecting to Telegram...
2024-01-15T10:30:01Z INFO channel Telegram connected as @my_picoclaw_assistant_bot
2024-01-15T10:30:01Z INFO main Gateway started on port 18790
```
## Step 5: Test Your Bot
### Send a Message
1. Open Telegram
2. Find your bot
3. Send `/start`
4. Send any message
```
You: Hello!
Bot: Hello! I'm your PicoClaw assistant. How can I help you today?
You: What time is it?
Bot: [Uses exec tool]
The current time is 10:35 AM.
You: Search for the weather
Bot: [Uses web_search tool]
Based on my search, the weather today is...
```
## Step 6: Debug Mode
If something isn't working, run with debug output:
```bash
picoclaw gateway --debug
```
This shows:
- Incoming messages
- LLM requests
- Tool calls
- Outgoing responses
## Step 7: Customize Bot Behavior
### Edit AGENT.md
Customize how your bot responds:
```bash
nano ~/.picoclaw/workspace/AGENT.md
```
```markdown
# Telegram Bot Behavior
You are a helpful Telegram assistant.
## Response Style
- Keep messages concise (Telegram users prefer brief responses)
- Use emoji sparingly
- Format long responses in paragraphs
## Capabilities
- Answer questions
- Search the web
- Manage files
## Commands
Respond helpfully to these commands:
- /start - Greet the user
- /help - Show available features
- /status - Show system status
```
### Restart Gateway
After editing:
```bash
# Stop the gateway (Ctrl+C)
# Start again
picoclaw gateway
```
## Step 8: Add More Users
### Get Their User IDs
Have other users message `@userinfobot` to get their IDs.
### Update Allow List
```json
{
"channels": {
"telegram": {
"enabled": true,
"token": "your-bot-token",
"allow_from": [123456789, 987654321, 555555555]
}
}
}
```
### Allow All Users (Not Recommended)
```json
{
"channels": {
"telegram": {
"enabled": true,
"token": "your-bot-token",
"allow_from": []
}
}
}
```
Warning: An empty `allow_from` allows anyone to use your bot and consume your API quota.
## Step 9: Group Chats
To use in Telegram groups:
### Get Group ID
1. Add `@RawDataBot` to your group
2. Send any message
3. It will reply with the group ID (negative number)
### Configure
```json
{
"channels": {
"telegram": {
"enabled": true,
"token": "your-bot-token",
"allow_from": [123456789, -1001234567890]
}
}
}
```
### Privacy Mode
By default, bots only see:
- Commands (messages starting with `/`)
- Messages where the bot is mentioned
- Replies to the bot's messages
To receive all messages, disable privacy mode:
1. Talk to @BotFather
2. Send `/setprivacy`
3. Select your bot
4. Choose "Disable"
## Step 10: Set Bot Commands
Define commands in BotFather:
1. Send `/setcommands` to @BotFather
2. Select your bot
3. Paste:
```
start - Start the bot
help - Show help
status - Check system status
clear - Clear conversation history
```
Now users will see command suggestions when typing `/`.
## Step 11: Run as Background Service
### Using Systemd (Linux)
Create a service file:
```bash
sudo nano /etc/systemd/system/picoclaw.service
```
```ini
[Unit]
Description=PicoClaw Gateway
After=network.target
[Service]
Type=simple
User=your-username
WorkingDirectory=/home/your-username
ExecStart=/usr/local/bin/picoclaw gateway
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
```
Enable and start:
```bash
sudo systemctl daemon-reload
sudo systemctl enable picoclaw
sudo systemctl start picoclaw
```
Check status:
```bash
sudo systemctl status picoclaw
```
### Using Docker
```bash
docker run -d \
--name picoclaw \
-v ~/.picoclaw:/root/.picoclaw \
picoclaw:latest gateway
```
## Troubleshooting
### Bot Not Responding
1. Check gateway is running:
```bash
picoclaw gateway --debug
```
2. Verify token is correct:
```bash
curl https://api.telegram.org/botYOUR_TOKEN/getMe
```
3. Check user ID is in allow list
### Conflict Error
```
Conflict: terminated by other getUpdates request
```
Only one instance can use the bot token:
1. Stop other instances
2. Wait a few seconds
3. Restart gateway
### Rate Limits
Telegram has rate limits:
- 30 messages/second to different users
- 1 message/second to same user
PicoClaw handles rate limiting automatically.
## Advanced Features
### Voice Messages
Enable voice transcription with Groq:
```json
{
"providers": {
"groq": {
"api_key": "your-groq-api-key"
}
},
"agents": {
"defaults": {
"voice_transcription": {
"enabled": true,
"provider": "groq"
}
}
}
}
```
### Webhook Mode (Production)
For production deployments, use webhooks instead of polling:
```json
{
"channels": {
"telegram": {
"enabled": true,
"token": "your-token",
"webhook": {
"enabled": true,
"url": "https://your-domain.com/telegram/webhook",
"port": 8443
}
}
}
}
```
## Next Steps
Now that you have a working Telegram bot:
- [Scheduled Tasks Tutorial](scheduled-tasks.md) - Automate periodic tasks
- [Multi-Agent Tutorial](multi-agent-setup.md) - Specialized agents
- [Telegram Channel Docs](../user-guide/channels/telegram.md) - Full configuration
## Summary
You learned:
- How to create a Telegram bot with BotFather
- How to configure the Telegram channel
- How to run the gateway
- How to customize bot behavior
- How to deploy as a service
Your PicoClaw assistant is now available on Telegram!

View file

@ -0,0 +1,92 @@
# Advanced Features
This section covers advanced configuration and features of PicoClaw for power users and complex deployment scenarios.
## Overview
PicoClaw provides several advanced features that enable sophisticated multi-agent architectures, robust model fallback chains, and fine-grained control over security and routing.
## Topics
### Multi-Agent System
- **[Multi-Agent Configuration](multi-agent.md)** - Configure multiple specialized agents with isolated workspaces and different models
### Routing and Sessions
- **[Message Routing](routing.md)** - Route messages from channels to specific agents using bindings
- **[Session Management](session-management.md)** - Handle conversation persistence, identity linking, and session scoping
### Reliability
- **[Model Fallbacks](model-fallbacks.md)** - Configure automatic fallback chains for high availability
### Security
- **[Security Sandbox](security-sandbox.md)** - Restrict file and command access to protect your system
### Configuration
- **[Environment Variables](environment-variables.md)** - Complete reference for all environment variables
### Voice Features
- **[Voice Transcription](voice-transcription.md)** - Enable voice message transcription using Groq Whisper
## Architecture Overview
PicoClaw follows a message bus architecture where:
1. **Channels** (Telegram, Discord, Slack, etc.) receive messages from users
2. **Routing** determines which agent handles each message based on bindings
3. **Agents** process messages using LLM providers and tools
4. **Sessions** maintain conversation state and history
```
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Telegram │ │ Discord │ │ Slack │
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
│ │ │
└───────────────────┼───────────────────┘
┌──────▼──────┐
│ Message Bus │
└──────┬──────┘
┌──────▼──────┐
│ Routing │
└──────┬──────┘
┌───────────────────┼───────────────────┐
│ │ │
┌──────▼──────┐ ┌──────▼──────┐ ┌──────▼──────┐
│ Agent A │ │ Agent B │ │ Agent C │
│ (Research) │ │ (Coding) │ │ (Assistant) │
└─────────────┘ └─────────────┘ └─────────────┘
```
## Configuration Hierarchy
PicoClaw uses a hierarchical configuration system:
1. **Defaults** - Default values built into the application
2. **Config File** - Settings from `~/.picoclaw/config.json`
3. **Environment Variables** - Override config file settings
4. **Command-line Flags** - Override all other settings
## Quick Reference
| Feature | Config Section | Key Setting |
|---------|---------------|-------------|
| Multi-agent | `agents.list` | `id`, `workspace`, `model` |
| Routing | `bindings` | `agent_id`, `match` |
| Sessions | `session` | `dm_scope`, `identity_links` |
| Fallbacks | `agents.defaults` | `model_fallbacks` |
| Sandbox | `agents.defaults` | `restrict_to_workspace` |
| Voice | `providers.groq` | `api_key` |
## Related Documentation
- [Configuration File Reference](../../configuration/config-file.md)
- [CLI Reference](../cli-reference.md)
- [Workspace Management](../workspace/README.md)

View file

@ -0,0 +1,363 @@
# Environment Variables Reference
All PicoClaw configuration options can be overridden with environment variables. This enables configuration management through environment files, container orchestration, and CI/CD pipelines.
## Naming Convention
Environment variables follow the pattern:
```
PICOCLAW_<SECTION>_<SUBSECTION>_<KEY>
```
The path corresponds to the JSON configuration structure:
```json
{
"section": {
"subsection": {
"key": "value"
}
}
}
```
Becomes: `PICOCLAW_SECTION_SUBSECTION_KEY`
## Agent Configuration
### Defaults
| Variable | Config Path | Description |
|----------|-------------|-------------|
| `PICOCLAW_AGENTS_DEFAULTS_WORKSPACE` | `agents.defaults.workspace` | Working directory |
| `PICOCLAW_AGENTS_DEFAULTS_RESTRICT_TO_WORKSPACE` | `agents.defaults.restrict_to_workspace` | Enable sandbox |
| `PICOCLAW_AGENTS_DEFAULTS_PROVIDER` | `agents.defaults.provider` | Default provider |
| `PICOCLAW_AGENTS_DEFAULTS_MODEL` | `agents.defaults.model` | Primary model |
| `PICOCLAW_AGENTS_DEFAULTS_MODEL_FALLBACKS` | `agents.defaults.model_fallbacks` | Fallback models (JSON array) |
| `PICOCLAW_AGENTS_DEFAULTS_IMAGE_MODEL` | `agents.defaults.image_model` | Image model |
| `PICOCLAW_AGENTS_DEFAULTS_IMAGE_MODEL_FALLBACKS` | `agents.defaults.image_model_fallbacks` | Image fallbacks |
| `PICOCLAW_AGENTS_DEFAULTS_MAX_TOKENS` | `agents.defaults.max_tokens` | Max response tokens |
| `PICOCLAW_AGENTS_DEFAULTS_TEMPERATURE` | `agents.defaults.temperature` | Response randomness |
| `PICOCLAW_AGENTS_DEFAULTS_MAX_TOOL_ITERATIONS` | `agents.defaults.max_tool_iterations` | Max tool loops |
### Examples
```bash
# Set primary model
export PICOCLAW_AGENTS_DEFAULTS_MODEL="anthropic/claude-opus-4-5"
# Set fallback models (JSON array)
export PICOCLAW_AGENTS_DEFAULTS_MODEL_FALLBACKS='["gpt-4o", "glm-4.7"]'
# Disable workspace restriction
export PICOCLAW_AGENTS_DEFAULTS_RESTRICT_TO_WORKSPACE="false"
```
## Provider Configuration
### Common Variables
| Variable Pattern | Description |
|------------------|-------------|
| `PICOCLAW_PROVIDERS_<NAME>_API_KEY` | API key for provider |
| `PICOCLAW_PROVIDERS_<NAME>_API_BASE` | API base URL |
| `PICOCLAW_PROVIDERS_<NAME>_PROXY` | Proxy URL |
| `PICOCLAW_PROVIDERS_<NAME>_AUTH_METHOD` | Auth method |
### Provider Names
Replace `<NAME>` with: `ANTHROPIC`, `OPENAI`, `OPENROUTER`, `GROQ`, `ZHIPU`, `GEMINI`, `OLLAMA`, `VLLM`, `NVIDIA`, `MOONSHOT`, `DEEPSEEK`, `GITHUB_COPILOT`
### Examples
```bash
# OpenRouter
export PICOCLAW_PROVIDERS_OPENROUTER_API_KEY="sk-or-v1-xxx"
export PICOCLAW_PROVIDERS_OPENROUTER_API_BASE="https://openrouter.ai/api/v1"
# Anthropic
export PICOCLAW_PROVIDERS_ANTHROPIC_API_KEY="sk-ant-xxx"
# Groq
export PICOCLAW_PROVIDERS_GROQ_API_KEY="gsk_xxx"
# OpenAI
export PICOCLAW_PROVIDERS_OPENAI_API_KEY="sk-xxx"
export PICOCLAW_PROVIDERS_OPENAI_WEB_SEARCH="true"
# Ollama (local)
export PICOCLAW_PROVIDERS_OLLAMA_API_BASE="http://localhost:11434/v1"
# vLLM (local)
export PICOCLAW_PROVIDERS_VLLM_API_BASE="http://localhost:8000/v1"
```
## Channel Configuration
### Telegram
| Variable | Description |
|----------|-------------|
| `PICOCLAW_CHANNELS_TELEGRAM_ENABLED` | Enable Telegram |
| `PICOCLAW_CHANNELS_TELEGRAM_TOKEN` | Bot token |
| `PICOCLAW_CHANNELS_TELEGRAM_PROXY` | Proxy URL |
| `PICOCLAW_CHANNELS_TELEGRAM_ALLOW_FROM` | Allowed user IDs (JSON array) |
### Discord
| Variable | Description |
|----------|-------------|
| `PICOCLAW_CHANNELS_DISCORD_ENABLED` | Enable Discord |
| `PICOCLAW_CHANNELS_DISCORD_TOKEN` | Bot token |
| `PICOCLAW_CHANNELS_DISCORD_ALLOW_FROM` | Allowed user IDs |
### Slack
| Variable | Description |
|----------|-------------|
| `PICOCLAW_CHANNELS_SLACK_ENABLED` | Enable Slack |
| `PICOCLAW_CHANNELS_SLACK_BOT_TOKEN` | Bot token (xoxb-...) |
| `PICOCLAW_CHANNELS_SLACK_APP_TOKEN` | App token (xapp-...) |
| `PICOCLAW_CHANNELS_SLACK_ALLOW_FROM` | Allowed user IDs |
### Other Channels
| Variable | Description |
|----------|-------------|
| `PICOCLAW_CHANNELS_WHATSAPP_ENABLED` | Enable WhatsApp |
| `PICOCLAW_CHANNELS_WHATSAPP_BRIDGE_URL` | Bridge WebSocket URL |
| `PICOCLAW_CHANNELS_FEISHU_ENABLED` | Enable Feishu |
| `PICOCLAW_CHANNELS_FEISHU_APP_ID` | Feishu App ID |
| `PICOCLAW_CHANNELS_FEISHU_APP_SECRET` | Feishu App Secret |
| `PICOCLAW_CHANNELS_LINE_ENABLED` | Enable LINE |
| `PICOCLAW_CHANNELS_LINE_CHANNEL_SECRET` | LINE Channel Secret |
| `PICOCLAW_CHANNELS_LINE_CHANNEL_ACCESS_TOKEN` | LINE Access Token |
| `PICOCLAW_CHANNELS_DINGTALK_ENABLED` | Enable DingTalk |
| `PICOCLAW_CHANNELS_DINGTALK_CLIENT_ID` | DingTalk Client ID |
| `PICOCLAW_CHANNELS_QQ_ENABLED` | Enable QQ |
| `PICOCLAW_CHANNELS_ONEBOT_ENABLED` | Enable OneBot |
| `PICOCLAW_CHANNELS_ONEBOT_WS_URL` | OneBot WebSocket URL |
| `PICOCLAW_CHANNELS_MAIXCAM_ENABLED` | Enable MaixCam |
### Examples
```bash
# Telegram
export PICOCLAW_CHANNELS_TELEGRAM_ENABLED="true"
export PICOCLAW_CHANNELS_TELEGRAM_TOKEN="123456:ABC..."
export PICOCLAW_CHANNELS_TELEGRAM_ALLOW_FROM='["123456789"]'
# Discord
export PICOCLAW_CHANNELS_DISCORD_ENABLED="true"
export PICOCLAW_CHANNELS_DISCORD_TOKEN="MTk4NjIyNDgzNDc..."
# Slack
export PICOCLAW_CHANNELS_SLACK_ENABLED="true"
export PICOCLAW_CHANNELS_SLACK_BOT_TOKEN="xoxb-xxx"
export PICOCLAW_CHANNELS_SLACK_APP_TOKEN="xapp-xxx"
```
## Tool Configuration
### Web Tools
| Variable | Description |
|----------|-------------|
| `PICOCLAW_TOOLS_WEB_BRAVE_ENABLED` | Enable Brave Search |
| `PICOCLAW_TOOLS_WEB_BRAVE_API_KEY` | Brave API key |
| `PICOCLAW_TOOLS_WEB_BRAVE_MAX_RESULTS` | Max results |
| `PICOCLAW_TOOLS_WEB_DUCKDUCKGO_ENABLED` | Enable DuckDuckGo |
| `PICOCLAW_TOOLS_WEB_DUCKDUCKGO_MAX_RESULTS` | Max results |
| `PICOCLAW_TOOLS_WEB_PERPLEXITY_ENABLED` | Enable Perplexity |
| `PICOCLAW_TOOLS_WEB_PERPLEXITY_API_KEY` | Perplexity API key |
| `PICOCLAW_TOOLS_WEB_PERPLEXITY_MAX_RESULTS` | Max results |
### Exec Tools
| Variable | Description |
|----------|-------------|
| `PICOCLAW_TOOLS_EXEC_ENABLE_DENY_PATTERNS` | Enable command filtering |
| `PICOCLAW_TOOLS_EXEC_CUSTOM_DENY_PATTERNS` | Custom blocked patterns |
### Cron Tools
| Variable | Description |
|----------|-------------|
| `PICOCLAW_TOOLS_CRON_EXEC_TIMEOUT_MINUTES` | Cron job timeout |
### Examples
```bash
# Enable Brave Search
export PICOCLAW_TOOLS_WEB_BRAVE_ENABLED="true"
export PICOCLAW_TOOLS_WEB_BRAVE_API_KEY="BSA..."
export PICOCLAW_TOOLS_WEB_BRAVE_MAX_RESULTS="5"
# Disable DuckDuckGo
export PICOCLAW_TOOLS_WEB_DUCKDUCKGO_ENABLED="false"
# Disable command filtering (not recommended)
export PICOCLAW_TOOLS_EXEC_ENABLE_DENY_PATTERNS="false"
```
## Gateway Configuration
| Variable | Description |
|----------|-------------|
| `PICOCLAW_GATEWAY_HOST` | Server host |
| `PICOCLAW_GATEWAY_PORT` | Server port |
### Example
```bash
export PICOCLAW_GATEWAY_HOST="0.0.0.0"
export PICOCLAW_GATEWAY_PORT="18790"
```
## Heartbeat Configuration
| Variable | Description |
|----------|-------------|
| `PICOCLAW_HEARTBEAT_ENABLED` | Enable periodic tasks |
| `PICOCLAW_HEARTBEAT_INTERVAL` | Check interval (minutes) |
### Example
```bash
export PICOCLAW_HEARTBEAT_ENABLED="true"
export PICOCLAW_HEARTBEAT_INTERVAL="30"
```
## Devices Configuration
| Variable | Description |
|----------|-------------|
| `PICOCLAW_DEVICES_ENABLED` | Enable device monitoring |
| `PICOCLAW_DEVICES_MONITOR_USB` | Monitor USB devices |
## Docker Example
Complete Docker environment configuration:
```dockerfile
# Dockerfile
FROM alpine:latest
ENV PICOCLAW_AGENTS_DEFAULTS_MODEL="anthropic/claude-opus-4-5"
ENV PICOCLAW_AGENTS_DEFAULTS_RESTRICT_TO_WORKSPACE="true"
ENV PICOCLAW_PROVIDERS_OPENROUTER_API_KEY="sk-or-v1-xxx"
ENV PICOCLAW_CHANNELS_TELEGRAM_ENABLED="true"
ENV PICOCLAW_CHANNELS_TELEGRAM_TOKEN="123456:ABC..."
ENV PICOCLAW_HEARTBEAT_ENABLED="false"
COPY picoclaw /usr/local/bin/
CMD ["picoclaw", "gateway"]
```
## Docker Compose Example
```yaml
version: '3'
services:
picoclaw:
image: picoclaw:latest
environment:
- PICOCLAW_AGENTS_DEFAULTS_MODEL=anthropic/claude-opus-4-5
- PICOCLAW_PROVIDERS_OPENROUTER_API_KEY=${OPENROUTER_API_KEY}
- PICOCLAW_PROVIDERS_GROQ_API_KEY=${GROQ_API_KEY}
- PICOCLAW_CHANNELS_TELEGRAM_ENABLED=true
- PICOCLAW_CHANNELS_TELEGRAM_TOKEN=${TELEGRAM_TOKEN}
- PICOCLAW_CHANNELS_DISCORD_ENABLED=true
- PICOCLAW_CHANNELS_DISCORD_TOKEN=${DISCORD_TOKEN}
volumes:
- picoclaw-data:/root/.picoclaw
restart: unless-stopped
volumes:
picoclaw-data:
```
## Kubernetes Example
```yaml
apiVersion: v1
kind: Secret
metadata:
name: picoclaw-secrets
type: Opaque
stringData:
openrouter-api-key: "sk-or-v1-xxx"
telegram-token: "123456:ABC..."
---
apiVersion: v1
kind: ConfigMap
metadata:
name: picoclaw-config
data:
PICOCLAW_AGENTS_DEFAULTS_MODEL: "anthropic/claude-opus-4-5"
PICOCLAW_CHANNELS_TELEGRAM_ENABLED: "true"
PICOCLAW_HEARTBEAT_ENABLED: "true"
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: picoclaw
spec:
template:
spec:
containers:
- name: picoclaw
image: picoclaw:latest
envFrom:
- configMapRef:
name: picoclaw-config
env:
- name: PICOCLAW_PROVIDERS_OPENROUTER_API_KEY
valueFrom:
secretKeyRef:
name: picoclaw-secrets
key: openrouter-api-key
- name: PICOCLAW_CHANNELS_TELEGRAM_TOKEN
valueFrom:
secretKeyRef:
name: picoclaw-secrets
key: telegram-token
```
## .env File Example
Create a `.env` file for local development:
```bash
# .env
PICOCLAW_AGENTS_DEFAULTS_MODEL=anthropic/claude-opus-4-5
PICOCLAW_AGENTS_DEFAULTS_MODEL_FALLBACKS='["gpt-4o", "glm-4.7"]'
# Providers
PICOCLAW_PROVIDERS_OPENROUTER_API_KEY=sk-or-v1-xxx
PICOCLAW_PROVIDERS_GROQ_API_KEY=gsk_xxx
PICOCLAW_PROVIDERS_ANTHROPIC_API_KEY=sk-ant-xxx
# Channels
PICOCLAW_CHANNELS_TELEGRAM_ENABLED=true
PICOCLAW_CHANNELS_TELEGRAM_TOKEN=123456:ABC...
PICOCLAW_CHANNELS_DISCORD_ENABLED=false
# Tools
PICOCLAW_TOOLS_WEB_DUCKDUCKGO_ENABLED=true
PICOCLAW_TOOLS_WEB_BRAVE_ENABLED=false
```
Load with:
```bash
source .env
picoclaw gateway
```
## Related Topics
- [Configuration File Reference](../../configuration/config-file.md) - JSON configuration
- [Security Sandbox](security-sandbox.md) - Security settings
- [Providers](../providers/README.md) - Provider configuration

View file

@ -0,0 +1,303 @@
# Model Fallbacks
PicoClaw supports automatic fallback chains for LLM models, ensuring high availability even when primary models are unavailable. This guide explains how to configure and understand fallback behavior.
## Overview
The fallback system provides:
- **High availability** - Automatically switch to backup models on failure
- **Rate limit handling** - Cooldown tracking for rate-limited providers
- **Intelligent error classification** - Only retry on retriable errors
- **Image model support** - Separate fallback chains for vision tasks
## Configuration
### Simple Fallbacks (Defaults)
Configure fallback models at the agent defaults level:
```json
{
"agents": {
"defaults": {
"model": "anthropic/claude-opus-4-5",
"model_fallbacks": ["anthropic/claude-sonnet-4", "gpt-4o", "glm-4.7"]
}
}
}
```
### Structured Model Configuration
For multi-agent setups, use the object format:
```json
{
"agents": {
"list": [
{
"id": "assistant",
"model": {
"primary": "anthropic/claude-opus-4-5",
"fallbacks": ["anthropic/claude-sonnet-4", "gpt-4o"]
}
}
]
}
}
```
### Image Model Fallbacks
Configure separate fallbacks for image/vision tasks:
```json
{
"agents": {
"defaults": {
"image_model": "anthropic/claude-opus-4-5",
"image_model_fallbacks": ["gpt-4o", "anthropic/claude-sonnet-4"]
}
}
}
```
## Model Format
Models are specified in the format `provider/model`:
```
anthropic/claude-opus-4-5
openrouter/anthropic/claude-opus-4-5
groq/llama-3.1-70b-versatile
openai/gpt-4o
zhipu/glm-4.7
```
If no provider is specified, the default provider is used.
## Fallback Behavior
### Execution Order
1. Try primary model
2. If failure, try first fallback
3. Continue through fallbacks until success
4. If all fail, return aggregate error
### Error Classification
The system classifies errors to decide whether to fallback:
| Error Type | Retriable | Action |
|------------|-----------|--------|
| Rate limit (429) | Yes | Fallback with cooldown |
| Server error (5xx) | Yes | Fallback immediately |
| Timeout | Yes | Fallback immediately |
| Invalid request (400) | No | Return error immediately |
| Auth error (401/403) | No | Return error immediately |
| Context canceled | No | Return error immediately |
### Cooldown Tracking
When a provider hits rate limits, it enters cooldown:
- **Duration**: Based on rate limit response
- **Effect**: Provider is skipped during cooldown
- **Recovery**: Provider used again after cooldown expires
### Success Handling
When a request succeeds:
1. Response is returned immediately
2. Provider cooldown is reset
3. No further fallbacks are attempted
## Fallback Chain Resolution
The system deduplicates models in the chain:
```json
{
"model": {
"primary": "gpt-4o",
"fallbacks": ["gpt-4o", "anthropic/claude-sonnet-4", "gpt-4o"]
}
}
```
Resolves to: `gpt-4o`, `anthropic/claude-sonnet-4`
## Example Scenarios
### Scenario 1: Primary Rate Limited
```
Request → claude-opus-4-5 (429 rate limit)
→ claude-sonnet-4 (success)
→ Return response
```
### Scenario 2: All Models Fail
```
Request → claude-opus-4-5 (500 server error)
→ gpt-4o (429 rate limit)
→ glm-4.7 (timeout)
→ Return aggregate error with all attempts
```
### Scenario 3: Non-Retriable Error
```
Request → claude-opus-4-5 (400 invalid request)
→ Return error immediately (no fallback)
```
### Scenario 4: Provider in Cooldown
```
Request → claude-opus-4-5 (skipped - in cooldown)
→ gpt-4o (success)
→ Return response
```
## Image Model Fallbacks
Image/vision requests use a simplified fallback chain:
- **No cooldown checks** - Image endpoints have different rate limits
- **Dimension errors abort** - Image size errors are non-retriable
- **Same fallback order** - Uses configured fallback list
### Configuration
```json
{
"agents": {
"defaults": {
"image_model": "anthropic/claude-opus-4-5",
"image_model_fallbacks": ["gpt-4o"]
}
}
}
```
## Subagent Model Overrides
Control which models spawned subagents use:
```json
{
"agents": {
"list": [
{
"id": "assistant",
"subagents": {
"allow_agents": ["researcher"],
"model": {
"primary": "gpt-4o-mini",
"fallbacks": ["glm-4-flash"]
}
}
}
]
}
}
```
## Debugging Fallbacks
Enable debug mode to see fallback decisions:
```bash
picoclaw agent --debug -m "Hello"
```
Debug output includes:
- Candidate model list
- Each attempt and its result
- Cooldown status
- Final successful model or error
### Example Debug Output
```
[providers] Resolved candidates: [claude-opus-4-5, claude-sonnet-4, gpt-4o]
[providers] Attempt 1: claude-opus-4-5 - rate limited (cooldown: 60s)
[providers] Attempt 2: claude-sonnet-4 - success (1.2s)
[providers] Fallback complete: claude-sonnet-4
```
## Environment Variables
Override model configuration with environment variables:
```bash
# Primary model
export PICOCLAW_AGENTS_DEFAULTS_MODEL="anthropic/claude-opus-4-5"
# Fallback models (JSON array)
export PICOCLAW_AGENTS_DEFAULTS_MODEL_FALLBACKS='["gpt-4o", "glm-4.7"]'
# Image model
export PICOCLAW_AGENTS_DEFAULTS_IMAGE_MODEL="gpt-4o"
```
## Best Practices
### 1. Order by Preference
List models in order of quality/preference:
```json
{
"model_fallbacks": ["claude-sonnet-4", "gpt-4o", "glm-4.7"]
}
```
### 2. Mix Providers
Use different providers to avoid single points of failure:
```json
{
"model_fallbacks": [
"anthropic/claude-sonnet-4",
"openai/gpt-4o",
"zhipu/glm-4.7"
]
}
```
### 3. Consider Costs
Order by cost when appropriate:
```json
{
"model_fallbacks": [
"groq/llama-3.1-70b-versatile",
"openai/gpt-4o-mini",
"anthropic/claude-sonnet-4"
]
}
```
### 4. Test Fallback Chain
Verify your fallback chain works:
```bash
# Simulate primary failure by using invalid API key
picoclaw agent --debug -m "Test"
```
## Related Topics
- [Multi-Agent System](multi-agent.md) - Agent-specific model configuration
- [Providers](../providers/README.md) - Configure LLM providers
- [Environment Variables](environment-variables.md) - Override settings

View file

@ -0,0 +1,316 @@
# Multi-Agent System
PicoClaw supports running multiple specialized agents, each with its own configuration, workspace, and model settings. This enables scenarios like having separate agents for research, coding, general assistance, or different teams.
## Overview
The multi-agent system allows you to:
- Create specialized agents for different tasks
- Isolate workspaces between agents
- Use different models for different agents
- Control which subagents can be spawned
- Route messages to specific agents based on source
## Configuration
Agents are defined in the `agents.list` array in your configuration file:
```json
{
"agents": {
"defaults": {
"workspace": "~/.picoclaw/workspace",
"restrict_to_workspace": true,
"model": "glm-4.7",
"max_tokens": 8192,
"temperature": 0.7
},
"list": [
{
"id": "assistant",
"default": true,
"name": "General Assistant",
"workspace": "~/.picoclaw/workspace/assistant",
"model": {
"primary": "anthropic/claude-opus-4-5",
"fallbacks": ["gpt-4o"]
},
"subagents": {
"allow_agents": ["researcher", "coder"]
}
},
{
"id": "researcher",
"name": "Research Agent",
"model": "perplexity/llama-3.1-sonar-large-128k-online",
"skills": ["web-search"]
},
{
"id": "coder",
"name": "Coding Agent",
"workspace": "~/.picoclaw/workspace/coder",
"model": "anthropic/claude-sonnet-4"
}
]
}
}
```
## Agent Properties
| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `id` | string | Yes | Unique agent identifier |
| `default` | bool | No | Whether this is the default agent |
| `name` | string | No | Human-readable display name |
| `workspace` | string | No | Agent-specific workspace directory |
| `model` | string/object | No | Model configuration (see below) |
| `skills` | []string | No | Filter available skills for this agent |
| `subagents` | object | No | Subagent spawning configuration |
## Model Configuration
The `model` property can be specified in two formats:
### String Format (Simple)
```json
{
"model": "anthropic/claude-opus-4-5"
}
```
### Object Format (With Fallbacks)
```json
{
"model": {
"primary": "anthropic/claude-opus-4-5",
"fallbacks": ["gpt-4o", "glm-4.7"]
}
}
```
See [Model Fallbacks](model-fallbacks.md) for detailed fallback configuration.
## Subagent Configuration
Control which agents can be spawned by an agent using the `subagents` property:
```json
{
"id": "assistant",
"subagents": {
"allow_agents": ["researcher", "coder"]
}
}
```
### Wildcard Permission
Allow spawning any agent:
```json
{
"subagents": {
"allow_agents": ["*"]
}
}
```
### Subagent Model Override
Override the model for spawned subagents:
```json
{
"subagents": {
"allow_agents": ["researcher"],
"model": {
"primary": "gpt-4o-mini",
"fallbacks": ["glm-4-flash"]
}
}
}
```
## Workspace Isolation
Each agent can have its own isolated workspace:
```
~/.picoclaw/workspace/
├── assistant/ # Agent: assistant
│ ├── sessions/
│ ├── memory/
│ ├── AGENT.md
│ └── IDENTITY.md
├── researcher/ # Agent: researcher
│ ├── sessions/
│ └── ...
└── coder/ # Agent: coder
├── sessions/
└── ...
```
### Benefits of Workspace Isolation
- **Separate conversation history** - Each agent maintains its own sessions
- **Independent memory** - Long-term memory (MEMORY.md) is agent-specific
- **Isolated skills** - Each agent can have custom skills
- **Different configurations** - AGENT.md can define agent-specific behavior
## Default Agent Selection
The default agent is selected when no binding matches. PicoClaw uses this priority:
1. Agent with `"default": true`
2. First agent in the list
3. Implicit "main" agent (if no agents defined)
## Implicit Single Agent
If no agents are defined in `agents.list`, PicoClaw creates an implicit "main" agent using the defaults:
```json
{
"agents": {
"defaults": {
"model": "glm-4.7"
}
}
}
```
This is equivalent to:
```json
{
"agents": {
"list": [
{
"id": "main",
"default": true
}
]
}
}
```
## Use Cases
### Personal vs Work Agents
```json
{
"agents": {
"list": [
{
"id": "personal",
"default": true,
"name": "Personal Assistant",
"workspace": "~/.picoclaw/workspace/personal"
},
{
"id": "work",
"name": "Work Assistant",
"workspace": "~/.picoclaw/workspace/work",
"model": "anthropic/claude-opus-4-5"
}
]
},
"bindings": [
{
"agent_id": "personal",
"match": { "channel": "telegram", "peer": { "kind": "user", "id": "123456789" } }
},
{
"agent_id": "work",
"match": { "channel": "slack", "team_id": "T12345" }
}
]
}
```
### Specialized Task Agents
```json
{
"agents": {
"list": [
{
"id": "assistant",
"default": true,
"name": "General Assistant",
"subagents": {
"allow_agents": ["researcher", "coder", "writer"]
}
},
{
"id": "researcher",
"name": "Research Specialist",
"model": "perplexity/llama-3.1-sonar-large-128k-online",
"skills": ["web-search"]
},
{
"id": "coder",
"name": "Code Specialist",
"model": "anthropic/claude-sonnet-4"
},
{
"id": "writer",
"name": "Writing Specialist",
"model": "anthropic/claude-opus-4-5"
}
]
}
}
```
### Model-Specific Agents
Use different models for different capabilities:
```json
{
"agents": {
"list": [
{
"id": "fast",
"name": "Fast Responses",
"model": "groq/llama-3.1-70b-versatile"
},
{
"id": "smart",
"name": "Complex Reasoning",
"model": "anthropic/claude-opus-4-5"
},
{
"id": "cheap",
"name": "Simple Tasks",
"model": "openai/gpt-4o-mini"
}
]
}
}
```
## Environment Variables
Override agent settings with environment variables:
```bash
# Default model for all agents
export PICOCLAW_AGENTS_DEFAULTS_MODEL="anthropic/claude-opus-4-5"
# Fallback models
export PICOCLAW_AGENTS_DEFAULTS_MODEL_FALLBACKS='["gpt-4o", "glm-4.7"]'
```
## Related Topics
- [Message Routing](routing.md) - Route messages to specific agents
- [Model Fallbacks](model-fallbacks.md) - Configure model fallback chains
- [Session Management](session-management.md) - Understand session scoping per agent
- [Spawn Tool](../tools/README.md) - Spawn subagents from conversations

View file

@ -0,0 +1,347 @@
# Message Routing
Message routing determines which agent handles incoming messages from different channels. PicoClaw uses a flexible binding system with a priority cascade for precise control.
## Overview
The routing system:
1. Receives messages from channels (Telegram, Discord, Slack, etc.)
2. Evaluates bindings to find a matching agent
3. Routes the message to the appropriate agent
4. Constructs the session key for conversation persistence
## Binding Configuration
Bindings are defined in the `bindings` array:
```json
{
"bindings": [
{
"agent_id": "personal",
"match": {
"channel": "telegram",
"peer": { "kind": "user", "id": "123456789" }
}
},
{
"agent_id": "work",
"match": {
"channel": "slack",
"team_id": "T12345"
}
}
]
}
```
## Binding Properties
| Property | Type | Description |
|----------|------|-------------|
| `agent_id` | string | Target agent ID |
| `match.channel` | string | Channel name (telegram, discord, slack, etc.) |
| `match.account_id` | string | Account filter (use `*` for wildcard) |
| `match.peer.kind` | string | Peer type: `user`, `group`, `channel` |
| `match.peer.id` | string | Peer/user ID |
| `match.guild_id` | string | Discord guild ID |
| `match.team_id` | string | Slack team ID |
## Priority Cascade
Bindings are evaluated in this priority order (highest to lowest):
1. **Peer binding** - Direct user/group match
2. **Parent peer binding** - Parent group for forwarded messages
3. **Guild binding** - Discord server match
4. **Team binding** - Slack workspace match
5. **Account binding** - Specific account match
6. **Channel wildcard** - Any message from channel (`account_id: "*"`)
7. **Default agent** - Fallback when no binding matches
## Match Examples
### Telegram User
Route messages from a specific Telegram user:
```json
{
"agent_id": "personal",
"match": {
"channel": "telegram",
"peer": { "kind": "user", "id": "123456789" }
}
}
```
### Telegram Group
Route all messages from a Telegram group:
```json
{
"agent_id": "team-bot",
"match": {
"channel": "telegram",
"peer": { "kind": "group", "id": "-1001234567890" }
}
}
```
### Discord Guild
Route all messages from a Discord server:
```json
{
"agent_id": "community-bot",
"match": {
"channel": "discord",
"guild_id": "123456789012345678"
}
}
```
### Slack Team
Route all messages from a Slack workspace:
```json
{
"agent_id": "work",
"match": {
"channel": "slack",
"team_id": "T12345"
}
}
```
### Channel Wildcard
Route all Telegram messages to an agent:
```json
{
"agent_id": "telegram-bot",
"match": {
"channel": "telegram",
"account_id": "*"
}
}
```
### Multi-Account
Route from a specific bot account:
```json
{
"agent_id": "bot-alpha",
"match": {
"channel": "telegram",
"account_id": "bot_123456"
}
}
```
## Session Key Construction
The routing system constructs session keys for conversation persistence. The session key format depends on the DM scope configuration:
### Default (Main Scope)
All conversations share one session:
```
main
```
### Per-Agent Scope
Separate sessions per agent:
```
agent:assistant:telegram:123456789
```
### Per-Channel Scope
Separate sessions per channel:
```
telegram:123456789
```
See [Session Management](session-management.md) for details.
## Routing Flow
```
Incoming Message
┌─────────────────┐
│ Filter by │
│ Channel │
└────────┬────────┘
┌─────────────────┐
│ Check Peer │──► Match? ──► Use Agent
│ Binding │
└────────┬────────┘
│ No
┌─────────────────┐
│ Check Parent │──► Match? ──► Use Agent
│ Peer Binding │
└────────┬────────┘
│ No
┌─────────────────┐
│ Check Guild/ │──► Match? ──► Use Agent
│ Team Binding │
└────────┬────────┘
│ No
┌─────────────────┐
│ Check Account │──► Match? ──► Use Agent
│ Binding │
└────────┬────────┘
│ No
┌─────────────────┐
│ Check Channel │──► Match? ──► Use Agent
│ Wildcard │
└────────┬────────┘
│ No
┌─────────────────┐
│ Use Default │
│ Agent │
└─────────────────┘
```
## Use Cases
### Personal Assistant with Work Separation
```json
{
"bindings": [
{
"agent_id": "personal",
"match": {
"channel": "telegram",
"peer": { "kind": "user", "id": "123456789" }
}
},
{
"agent_id": "work",
"match": {
"channel": "slack",
"team_id": "T12345"
}
},
{
"agent_id": "work",
"match": {
"channel": "discord",
"guild_id": "987654321"
}
}
]
}
```
### Team Bot for Group Chats
```json
{
"bindings": [
{
"agent_id": "team-assistant",
"match": {
"channel": "telegram",
"peer": { "kind": "group", "id": "-1001234567890" }
}
},
{
"agent_id": "team-assistant",
"match": {
"channel": "discord",
"guild_id": "123456789012345678"
}
}
]
}
```
### Multiple Discord Servers
```json
{
"bindings": [
{
"agent_id": "community-bot",
"match": {
"channel": "discord",
"guild_id": "111111111111111111"
}
},
{
"agent_id": "support-bot",
"match": {
"channel": "discord",
"guild_id": "222222222222222222"
}
}
]
}
```
### Channel-Specific Agents
```json
{
"bindings": [
{
"agent_id": "telegram-bot",
"match": {
"channel": "telegram",
"account_id": "*"
}
},
{
"agent_id": "discord-bot",
"match": {
"channel": "discord",
"account_id": "*"
}
}
]
}
```
## Debugging Routing
Enable debug mode to see routing decisions:
```bash
picoclaw gateway --debug
```
Debug output includes:
- Which bindings were evaluated
- Which binding matched (if any)
- Final agent selection
- Session key construction
## Related Topics
- [Multi-Agent System](multi-agent.md) - Define multiple agents
- [Session Management](session-management.md) - Understand session persistence
- [Channels](../channels/README.md) - Configure chat platform integrations

View file

@ -0,0 +1,320 @@
# Security Sandbox
PicoClaw includes a security sandbox to restrict file system access and command execution. This protects your system from accidental or malicious operations by the AI.
## Overview
The security sandbox provides:
- **Workspace restriction** - File operations limited to workspace directory
- **Command filtering** - Dangerous commands are blocked
- **Path traversal prevention** - Cannot access files outside workspace
- **Configurable patterns** - Add custom deny patterns
## Workspace Restriction
### Configuration
Enable or disable workspace restriction:
```json
{
"agents": {
"defaults": {
"restrict_to_workspace": true,
"workspace": "~/.picoclaw/workspace"
}
}
}
```
### Behavior When Enabled
When `restrict_to_workspace` is `true` (default):
- File read/write operations must be within workspace
- Shell commands execute from workspace directory
- Path traversal attempts (`../`) are blocked
- Absolute paths outside workspace are rejected
### Behavior When Disabled
When `restrict_to_workspace` is `false`:
- Full file system access is allowed
- Commands can run from any directory
- Use with caution in production environments
## Command Filtering
### Default Blocked Patterns
The following dangerous commands are always blocked:
| Category | Patterns |
|----------|----------|
| File deletion | `rm -rf`, `del /f`, `rmdir /s` |
| Disk operations | `format`, `mkfs`, `diskpart`, `dd if=` |
| System control | `shutdown`, `reboot`, `poweroff` |
| Privilege escalation | `sudo`, `chmod 777`, `chown` |
| Process control | `pkill`, `killall`, `kill -9` |
| Shell injection | `$(...)`, backticks, `eval`, `source` |
| Remote execution | `curl | sh`, `wget | bash` |
| Package management | `npm install -g`, `pip install --user`, `apt install` |
| Container escape | `docker run`, `docker exec` |
| Network | `ssh @` |
| Version control | `git push`, `git force` |
### Custom Deny Patterns
Add additional patterns to block:
```json
{
"tools": {
"exec": {
"enable_deny_patterns": true,
"custom_deny_patterns": [
"wget.*",
"curl.*",
"nc.*-l",
"python.*-m.*http"
]
}
}
}
```
### Disable All Filtering
Disable command filtering entirely (not recommended):
```json
{
"tools": {
"exec": {
"enable_deny_patterns": false
}
}
}
```
## Path Traversal Protection
The sandbox detects and blocks path traversal attempts:
| Attempt | Blocked? |
|---------|----------|
| `../../../etc/passwd` | Yes |
| `..\..\..\windows\system32` | Yes |
| `/etc/passwd` | Yes (outside workspace) |
| `~/secret.txt` | Yes (outside workspace) |
| `workspace/file.txt` | No (relative, within workspace) |
| `/home/user/.picoclaw/workspace/file.txt` | No (absolute, within workspace) |
## Configuration Reference
### Agent Defaults
```json
{
"agents": {
"defaults": {
"workspace": "~/.picoclaw/workspace",
"restrict_to_workspace": true
}
}
}
```
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `workspace` | string | `~/.picoclaw/workspace` | Working directory |
| `restrict_to_workspace` | bool | `true` | Enable sandbox restrictions |
### Exec Tool Configuration
```json
{
"tools": {
"exec": {
"enable_deny_patterns": true,
"custom_deny_patterns": []
}
}
}
```
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `enable_deny_patterns` | bool | `true` | Enable command filtering |
| `custom_deny_patterns` | []string | `[]` | Additional patterns to block |
## Environment Variables
Override security settings with environment variables:
```bash
# Disable workspace restriction (not recommended)
export PICOCLAW_AGENTS_DEFAULTS_RESTRICT_TO_WORKSPACE="false"
# Disable command filtering (not recommended)
export PICOCLAW_TOOLS_EXEC_ENABLE_DENY_PATTERNS="false"
# Custom deny patterns
export PICOCLAW_TOOLS_EXEC_CUSTOM_DENY_PATTERNS='["wget.*", "curl.*"]'
```
## Multi-Agent Security
Each agent can have its own security settings:
```json
{
"agents": {
"list": [
{
"id": "trusted",
"workspace": "~/.picoclaw/workspace/trusted",
"restrict_to_workspace": false
},
{
"id": "sandboxed",
"workspace": "~/.picoclaw/workspace/sandboxed",
"restrict_to_workspace": true
}
]
}
}
```
### Workspace Isolation
Different agents with isolated workspaces:
```
~/.picoclaw/workspace/
├── agent-a/ # Agent A's sandbox
│ ├── files/
│ └── sessions/
├── agent-b/ # Agent B's sandbox
│ ├── files/
│ └── sessions/
└── shared/ # Shared workspace (if configured)
```
## Security Best Practices
### 1. Keep Sandbox Enabled
Leave `restrict_to_workspace` enabled for production:
```json
{
"agents": {
"defaults": {
"restrict_to_workspace": true
}
}
}
```
### 2. Use Dedicated Workspace
Create a dedicated workspace directory:
```bash
mkdir -p ~/.picoclaw/workspace
```
### 3. Review Custom Patterns
When adding custom deny patterns, test them thoroughly:
```json
{
"tools": {
"exec": {
"custom_deny_patterns": [
"\\bmysqldump\\b",
"\\bpg_dump\\b"
]
}
}
}
```
### 4. Separate Agent Workspaces
Use different workspaces for different trust levels:
```json
{
"agents": {
"list": [
{
"id": "production",
"workspace": "~/.picoclaw/workspace/prod",
"restrict_to_workspace": true
},
{
"id": "development",
"workspace": "~/.picoclaw/workspace/dev",
"restrict_to_workspace": true
}
]
}
}
```
### 5. Monitor Logs
Enable debug logging to monitor blocked operations:
```bash
picoclaw agent --debug
```
## Error Messages
When operations are blocked, users see clear error messages:
| Error | Cause |
|-------|-------|
| `Command blocked by safety guard (dangerous pattern detected)` | Command matches deny pattern |
| `Command blocked by safety guard (path traversal detected)` | Path contains `../` or `..\` |
| `Command blocked by safety guard (path outside working dir)` | Absolute path outside workspace |
| `access denied: path outside workspace` | File operation outside workspace |
## Troubleshooting
### Legitimate Commands Blocked
If safe commands are being blocked:
1. Check if command matches a deny pattern
2. Consider adding to allowlist (if configured)
3. Adjust custom deny patterns
### Cannot Access Files
If file access is denied:
1. Verify file is within workspace
2. Check workspace path configuration
3. Ensure `restrict_to_workspace` is configured correctly
### Need More Access
For trusted environments:
1. Disable workspace restriction temporarily
2. Use a separate agent with relaxed security
3. Move required files into workspace
## Related Topics
- [Multi-Agent System](multi-agent.md) - Isolated agent workspaces
- [Exec Tool](../tools/exec.md) - Command execution configuration
- [Filesystem Tool](../tools/filesystem.md) - File operations
- [Workspace Management](../workspace/README.md) - Workspace structure

View file

@ -0,0 +1,339 @@
# Session Management
PicoClaw maintains conversation history through a session management system. Sessions persist across conversations and can be scoped differently based on configuration.
## Overview
The session system provides:
- **Conversation persistence** - Messages are saved and loaded automatically
- **Session scoping** - Control how sessions are shared across agents/channels
- **Identity linking** - Share sessions across different platforms
- **History management** - Automatic summarization for long conversations
## Session Storage
Sessions are stored as JSON files in the workspace:
```
~/.picoclaw/workspace/
└── sessions/
├── main.json # Main session
├── telegram_123456789.json # Telegram user session
├── discord_987654321.json # Discord user session
└── agent_assistant_telegram_123456789.json # Agent-specific session
```
## Session Structure
Each session file contains:
```json
{
"key": "telegram:123456789",
"messages": [
{
"role": "user",
"content": "Hello!"
},
{
"role": "assistant",
"content": "Hi! How can I help you?"
}
],
"summary": "Previous conversation about project setup...",
"created": "2024-01-15T10:30:00Z",
"updated": "2024-01-15T11:45:00Z"
}
```
### Session Fields
| Field | Type | Description |
|-------|------|-------------|
| `key` | string | Unique session identifier |
| `messages` | array | Conversation history |
| `summary` | string | Auto-generated summary of older messages |
| `created` | timestamp | Session creation time |
| `updated` | timestamp | Last update time |
## DM Scope Configuration
Control how direct message sessions are scoped with `session.dm_scope`:
```json
{
"session": {
"dm_scope": "per-agent"
}
}
```
### Scope Options
| Value | Description | Session Key Format |
|-------|-------------|-------------------|
| `main` | Single shared session (default) | `main` |
| `per-agent` | Separate session per agent | `agent:{agent_id}:{channel}:{user_id}` |
| `per-channel` | Separate session per channel | `{channel}:{user_id}` |
### Main Scope
All conversations use a single session:
```json
{
"session": {
"dm_scope": "main"
}
}
```
Best for: Simple single-agent setups
### Per-Agent Scope
Each agent maintains its own conversation history:
```json
{
"session": {
"dm_scope": "per-agent"
}
}
```
Best for: Multi-agent setups where each agent should have independent context
### Per-Channel Scope
Separate sessions for each messaging platform:
```json
{
"session": {
"dm_scope": "per-channel"
}
}
```
Best for: Users who want platform-specific conversations
## Identity Links
Share sessions across different platforms by linking user identities:
```json
{
"session": {
"dm_scope": "per-agent",
"identity_links": {
"telegram:123456789": ["discord:987654321", "slack:U12345"]
}
}
}
```
### How Identity Links Work
1. User sends message from Telegram (ID: 123456789)
2. PicoClaw checks `identity_links` for linked accounts
3. Session key uses canonical identity (first in array)
4. Same user on Discord uses the same session
### Example Configuration
```json
{
"session": {
"dm_scope": "per-agent",
"identity_links": {
"telegram:123456789": ["discord:987654321"],
"telegram:987654321": ["slack:U67890", "discord:111222333"]
}
}
}
```
## Session Key Construction
Session keys uniquely identify conversations. The format depends on context:
### DM Sessions
```
{scope_prefix}{channel}:{user_id}
```
Examples:
- `main` (main scope)
- `telegram:123456789` (per-channel)
- `agent:assistant:telegram:123456789` (per-agent)
### Group Sessions
```
{channel}:group:{group_id}
```
Example:
- `telegram:group:-1001234567890`
### Channel Sessions
```
{channel}:channel:{channel_id}
```
Example:
- `telegram:channel:@mychannel`
## History Management
### Automatic Summarization
When conversation history grows too long, PicoClaw automatically:
1. Keeps recent messages (last N messages)
2. Generates a summary of older messages
3. Stores the summary in the session
### History Truncation
The session manager provides methods for history management:
- `TruncateHistory(key, keepLast)` - Keep only the last N messages
- `SetSummary(key, summary)` - Store a conversation summary
### Manual History Control
You can control history programmatically or through tools:
```bash
# Clear session history
rm ~/.picoclaw/workspace/sessions/telegram_123456789.json
```
## Session Manager API
The session manager provides these operations:
| Method | Description |
|--------|-------------|
| `GetOrCreate(key)` | Get existing session or create new |
| `AddMessage(key, role, content)` | Add a message to session |
| `AddFullMessage(key, message)` | Add message with tool calls |
| `GetHistory(key)` | Get all messages |
| `SetHistory(key, messages)` | Replace all messages |
| `GetSummary(key)` | Get session summary |
| `SetSummary(key, summary)` | Set session summary |
| `TruncateHistory(key, keepLast)` | Trim message history |
| `Save(key)` | Persist session to disk |
## Session Persistence
### Automatic Saving
Sessions are automatically saved:
- After each message exchange
- When summaries are generated
- On graceful shutdown
### File Format
Sessions use JSON format with indentation for readability:
```json
{
"key": "telegram:123456789",
"messages": [...],
"summary": "...",
"created": "2024-01-15T10:30:00Z",
"updated": "2024-01-15T11:45:00Z"
}
```
### Safe File Writing
Sessions use atomic write operations:
1. Write to temporary file
2. Sync to disk
3. Rename to final location
This prevents corruption from crashes or power failures.
## Use Cases
### Cross-Platform Identity
User wants the same conversation on Telegram and Discord:
```json
{
"session": {
"dm_scope": "per-agent",
"identity_links": {
"telegram:123456789": ["discord:987654321"]
}
}
}
```
### Isolated Work Conversations
Keep work Slack separate from personal Telegram:
```json
{
"session": {
"dm_scope": "per-channel"
}
}
```
### Agent-Specific Context
Different agents have different conversation history:
```json
{
"session": {
"dm_scope": "per-agent"
},
"agents": {
"list": [
{ "id": "personal", "default": true },
{ "id": "work" }
]
}
}
```
## Troubleshooting
### Session Not Persisting
Check:
1. Workspace directory exists and is writable
2. `sessions/` subdirectory exists
3. No file permission issues
### Wrong Session Used
1. Check `dm_scope` configuration
2. Verify `identity_links` mapping
3. Enable debug mode to see session key construction
### History Too Long
1. Sessions auto-summarize when long
2. Manually clear session file if needed
3. Consider per-agent scope to isolate contexts
## Related Topics
- [Message Routing](routing.md) - How sessions are selected
- [Multi-Agent System](multi-agent.md) - Agent-specific sessions
- [Workspace Management](../workspace/README.md) - Workspace structure

View file

@ -0,0 +1,248 @@
# Voice Transcription
PicoClaw supports voice message transcription using Groq's Whisper API. This allows users to send voice messages through supported channels and have them automatically transcribed for the AI to process.
## Overview
Voice transcription provides:
- **Automatic transcription** - Voice messages converted to text
- **Multi-language support** - Whisper supports 99+ languages
- **Fast processing** - Groq's infrastructure provides quick transcription
- **Seamless integration** - Transcribed text feeds directly into conversation
## Requirements
- Groq API key configured
- Channel that supports voice messages (Telegram, Discord, etc.)
- Audio format supported by Whisper (MP3, WAV, M4A, etc.)
## Configuration
### Groq Provider Setup
Configure the Groq provider with your API key:
```json
{
"providers": {
"groq": {
"api_key": "gsk_xxx"
}
}
}
```
### Environment Variable
Alternatively, use environment variables:
```bash
export PICOCLAW_PROVIDERS_GROQ_API_KEY="gsk_xxx"
```
## How It Works
### Processing Flow
1. User sends voice message to channel (Telegram, Discord, etc.)
2. Channel downloads audio file
3. PicoClaw sends audio to Groq Whisper API
4. Transcription text is received
5. Transcribed text is processed as a regular message
### Architecture
```
Voice Message
┌─────────────────┐
│ Channel Handler │
│ (Telegram/etc) │
└────────┬────────┘
┌─────────────────┐
│ Voice Download │
└────────┬────────┘
┌─────────────────┐
│ Groq Whisper │
│ API │
└────────┬────────┘
┌─────────────────┐
│ Transcribed │
│ Text Message │
└─────────────────┘
```
## Supported Formats
Groq Whisper supports common audio formats:
| Format | Extension | Notes |
|--------|-----------|-------|
| MP3 | `.mp3` | Most common |
| WAV | `.wav` | Uncompressed |
| M4A | `.m4a` | Apple format |
| WebM | `.webm` | Web format |
| OGG | `.ogg` | Telegram default |
| FLAC | `.flac` | Lossless |
| MP4 | `.mp4` | Video container (audio extracted) |
## Channel Support
Voice transcription is supported in channels that implement voice message handling:
### Telegram
Telegram voice messages (OGG format) are automatically transcribed:
1. User sends voice message
2. Telegram downloads audio
3. Audio is transcribed
4. Text is processed
### Discord
Discord voice messages are transcribed when available:
1. User uploads voice message
2. Audio file is downloaded
3. Audio is transcribed
4. Text is processed
## API Details
### Endpoint
Voice transcription uses Groq's OpenAI-compatible endpoint:
```
POST https://api.groq.com/openai/v1/audio/transcriptions
```
### Model
PicoClaw uses `whisper-large-v3` for transcription:
- High accuracy
- Multi-language support
- Fast processing on Groq infrastructure
### Response Format
```json
{
"text": "Hello, this is a transcribed message.",
"language": "en",
"duration": 5.2
}
```
## Configuration Options
### Enable/Disable
Voice transcription is enabled when a Groq API key is configured. To disable:
```bash
# Remove or empty the API key
unset PICOCLAW_PROVIDERS_GROQ_API_KEY
```
### Timeout
Voice transcription has a 60-second timeout for API requests. Long audio files may take longer to process.
## Debugging
Enable debug mode to see transcription details:
```bash
picoclaw gateway --debug
```
### Debug Output
```
[voice] Starting transcription: voice_message.ogg
[voice] Audio file details: size_bytes=245760, file_name=voice_message.ogg
[voice] Sending transcription request to Groq API
[voice] Transcription completed: text_length=45, language=en, duration=3.5
```
## Troubleshooting
### Transcription Not Working
1. **Check API key**: Ensure Groq API key is configured
```bash
echo $PICOCLAW_PROVIDERS_GROQ_API_KEY
```
2. **Check channel support**: Verify channel handles voice messages
3. **Check audio format**: Ensure format is supported by Whisper
4. **Check logs**: Enable debug mode for detailed logging
### Poor Transcription Quality
1. **Audio quality**: Better quality audio yields better transcription
2. **Background noise**: Noisy audio may reduce accuracy
3. **Language**: Ensure correct language is being spoken
4. **Audio length**: Very short clips may have reduced accuracy
### API Errors
Common API errors:
| Error | Cause | Solution |
|-------|-------|----------|
| 401 Unauthorized | Invalid API key | Check API key |
| 413 Payload Too Large | Audio file too large | Compress or shorten audio |
| 429 Rate Limited | Too many requests | Wait and retry |
| 500 Server Error | Groq service issue | Retry later |
## Privacy Considerations
- Audio files are sent to Groq's servers for transcription
- Files are processed in real-time and not stored by Groq
- Consider privacy implications for sensitive conversations
- Review Groq's privacy policy for details
## Cost Considerations
Groq Whisper pricing:
- Free tier available with rate limits
- Paid tier for higher volume
- Monitor usage to avoid unexpected costs
Check [Groq's pricing page](https://groq.com/pricing) for current rates.
## Example Usage
### Telegram Voice Message
1. Open Telegram chat with bot
2. Hold microphone button and record message
3. Release to send
4. Bot transcribes and responds to text
### Discord Voice Message
1. Open Discord channel with bot
2. Upload or record voice message
3. Bot transcribes and responds to text
## Related Topics
- [Channels](../channels/README.md) - Configure chat platforms
- [Providers](../providers/README.md) - Configure LLM providers
- [Environment Variables](environment-variables.md) - Configuration options

View file

@ -0,0 +1,137 @@
# Channels Overview
PicoClaw supports multiple chat platforms, allowing you to interact with your AI assistant through your preferred messaging app.
## Supported Channels
| Channel | Setup Difficulty | Features |
|---------|------------------|----------|
| [Telegram](telegram.md) | Easy | Full support, voice transcription |
| [Discord](discord.md) | Easy | Full support, voice transcription |
| [Slack](slack.md) | Medium | Full support, voice transcription |
| [LINE](line.md) | Medium | Full support, webhooks |
| [QQ](qq.md) | Easy | Basic support |
| [DingTalk](dingtalk.md) | Medium | Basic support |
| [WhatsApp](whatsapp.md) | Medium | Requires bridge |
| [Feishu/Lark](feishu-lark.md) | Medium | Enterprise features |
| [OneBot](onebot.md) | Medium | Universal protocol |
| [MaixCam](maixcam.md) | Easy | Hardware device |
## Quick Setup
### 1. Choose a Channel
Select the platform you want to use.
### 2. Get Credentials
Each channel requires different credentials:
- **Telegram**: Bot token from @BotFather
- **Discord**: Bot token from Developer Portal
- **Slack**: Bot token and App token
- **LINE**: Channel secret and access token
### 3. Configure
Add credentials to `~/.picoclaw/config.json`:
```json
{
"channels": {
"telegram": {
"enabled": true,
"token": "YOUR_BOT_TOKEN",
"allow_from": ["YOUR_USER_ID"]
}
}
}
```
### 4. Start Gateway
```bash
picoclaw gateway
```
## Common Options
All channels support:
| Option | Description |
|--------|-------------|
| `enabled` | Enable/disable the channel |
| `allow_from` | Whitelist of allowed user IDs (empty = all users) |
## Access Control
Use `allow_from` to restrict who can interact with your bot:
```json
{
"channels": {
"telegram": {
"enabled": true,
"token": "YOUR_TOKEN",
"allow_from": ["123456789", "987654321"]
}
}
}
```
An empty `allow_from` allows all users.
## Voice Transcription
With Groq configured, voice messages are automatically transcribed on:
- Telegram
- Discord
- Slack
- OneBot
```json
{
"providers": {
"groq": {
"api_key": "gsk_xxx"
}
}
}
```
## Multi-Channel Setup
You can enable multiple channels simultaneously:
```json
{
"channels": {
"telegram": {
"enabled": true,
"token": "telegram-token"
},
"discord": {
"enabled": true,
"token": "discord-token"
},
"slack": {
"enabled": true,
"bot_token": "xoxb-token",
"app_token": "xapp-token"
}
}
}
```
## Channel-Specific Guides
- [Telegram Setup](telegram.md)
- [Discord Setup](discord.md)
- [Slack Setup](slack.md)
- [LINE Setup](line.md)
- [QQ Setup](qq.md)
- [DingTalk Setup](dingtalk.md)
- [WhatsApp Setup](whatsapp.md)
- [Feishu/Lark Setup](feishu-lark.md)
- [OneBot Setup](onebot.md)
- [MaixCam Setup](maixcam.md)

View file

@ -0,0 +1,184 @@
# DingTalk Setup
DingTalk (钉钉) is a popular enterprise messaging and collaboration platform in China.
## Prerequisites
- A DingTalk account
- Admin access to a DingTalk organization (or ability to create one)
## Step 1: Create a DingTalk Application
1. Go to [DingTalk Developer Console](https://open-dev.dingtalk.com/)
2. Log in with your DingTalk account
3. Click **"Create Application"** (创建应用)
4. Select **"Enterprise Internal Application"** (企业内部应用)
5. Fill in the application information:
- Application name (e.g., "PicoClaw Bot")
- Application description
- Application logo
6. Click **"Confirm"**
## Step 2: Get Client Credentials
1. In your application dashboard, go to **"Application Information"** (应用信息)
2. Copy the **"Client ID"** (ClientID)
3. Copy the **"Client Secret"** (ClientSecret)
## Step 3: Configure Bot Capabilities
1. Go to **"Robot & Message Push"** (机器人与消息推送)
2. Enable the robot capability
3. Configure message receiving:
- Enable **"Stream Mode"** (Stream Mode / 流式模式)
- This allows real-time message receiving via WebSocket
## Step 4: Set Permissions
1. Go to **"Permission Management"** (权限管理)
2. Request these permissions:
- **"Chat with users"** (与企业内人员聊天)
- **"Send messages"** (发送消息)
3. Wait for approval if required
## Step 5: Configure PicoClaw
Edit `~/.picoclaw/config.json`:
```json
{
"channels": {
"dingtalk": {
"enabled": true,
"client_id": "YOUR_CLIENT_ID",
"client_secret": "YOUR_CLIENT_SECRET",
"allow_from": []
}
}
}
```
| Option | Required | Description |
|--------|----------|-------------|
| `enabled` | Yes | Set to `true` to enable |
| `client_id` | Yes | Client ID from DingTalk Developer Console |
| `client_secret` | Yes | Client Secret from DingTalk Developer Console |
| `allow_from` | No | Array of allowed user IDs |
## Step 6: Start the Gateway
```bash
picoclaw gateway
```
You should see:
```
Starting DingTalk channel (Stream Mode)...
DingTalk channel started (Stream Mode)
```
## Step 7: Test
### Single Chat
1. Open DingTalk
2. Find your bot in the organization
3. Send a message to the bot
4. The bot should respond!
### Group Chat
1. Add the bot to a DingTalk group
2. Mention the bot or send a message
3. The bot should respond!
## Features
### Stream Mode
PicoClaw uses DingTalk's Stream Mode for real-time message receiving via WebSocket. This provides:
- Instant message delivery
- No need for a public webhook URL
- Automatic reconnection
### Markdown Support
The bot sends responses in Markdown format with a title header.
### Group Chat Support
The bot works in both:
- One-on-one conversations
- Group conversations
## Troubleshooting
### Bot not responding
1. Verify client_id and client_secret are correct
2. Check that Stream Mode is enabled
3. Ensure permissions are approved
4. Check the gateway is running
### "Authentication failed" error
1. Verify client_id and client_secret are correct
2. Check if the application is published/active
3. Ensure no extra whitespace in credentials
### Stream connection issues
1. Check your network allows WebSocket connections
2. Verify firewall allows outgoing connections to DingTalk servers
3. Check logs for specific error messages
### Permission denied errors
1. Go to DingTalk Developer Console
2. Verify all required permissions are granted
3. Request additional permissions if needed
## Advanced Configuration
### Allow Specific Users
```json
{
"channels": {
"dingtalk": {
"enabled": true,
"client_id": "YOUR_CLIENT_ID",
"client_secret": "YOUR_CLIENT_SECRET",
"allow_from": ["user123", "user456"]
}
}
}
```
### Multi-Tenant Setup
For multiple organizations, create separate applications and use separate configurations.
## Important Notes
### Enterprise Application
DingTalk bots require an enterprise application. Personal bots are not supported.
### Approval Process
Some permissions require admin approval within your DingTalk organization.
### Rate Limits
DingTalk has rate limits on API calls. For high-volume usage, consider:
- Implementing message batching
- Contacting DingTalk for higher limits
## See Also
- [Channels Overview](README.md)
- [Gateway Command](../cli/gateway.md)
- [DingTalk Developer Documentation](https://open.dingtalk.com/document/)
- [Troubleshooting](../../operations/troubleshooting.md)

View file

@ -0,0 +1,147 @@
# Discord Setup
Discord is great for community servers and personal use.
## Prerequisites
- A Discord account
- Admin access to a Discord server (or ability to create one)
## Step 1: Create a Discord Application
1. Go to [Discord Developer Portal](https://discord.com/developers/applications)
2. Click **"New Application"**
3. Give it a name (e.g., "PicoClaw Bot")
4. Click **"Create"**
## Step 2: Create a Bot
1. In your application, go to **"Bot"** in the left sidebar
2. Click **"Add Bot"**
3. Confirm by clicking **"Yes, do it!"**
## Step 3: Get Bot Token
1. In the Bot settings, find **"Token"**
2. Click **"Reset Token"** if needed
3. Copy the token (starts with `MTk4Nj...`)
## Step 4: Enable Intents
In the Bot settings, enable:
- **MESSAGE CONTENT INTENT** (required)
- **SERVER MEMBERS INTENT** (optional, for member-based features)
Click **"Save Changes"**.
## Step 5: Get Your User ID
1. Open Discord
2. Go to **Settings** → **Advanced**
3. Enable **"Developer Mode"**
4. Right-click your avatar in any chat
5. Select **"Copy User ID"**
## Step 6: Configure PicoClaw
Edit `~/.picoclaw/config.json`:
```json
{
"channels": {
"discord": {
"enabled": true,
"token": "MTk4NjIyNDgzNDc...",
"allow_from": ["123456789012345678"]
}
}
}
```
| Option | Required | Description |
|--------|----------|-------------|
| `enabled` | Yes | Set to `true` to enable |
| `token` | Yes | Bot token |
| `allow_from` | No | Array of allowed user IDs |
## Step 7: Invite the Bot
1. In the Developer Portal, go to **"OAuth2"** → **"URL Generator"**
2. Under **Scopes**, check `bot`
3. Under **Bot Permissions**, check:
- `Send Messages`
- `Read Message History`
- (Optional) `Attach Files`
4. Copy the generated URL
5. Open the URL in your browser
6. Select your server and authorize the bot
## Step 8: Start the Gateway
```bash
picoclaw gateway
```
You should see:
```
✓ Channels enabled: discord
✓ Gateway started on 0.0.0.0:18790
```
## Step 9: Test
1. Go to your Discord server
2. Find the channel where the bot is present
3. Send a message
4. The bot should respond!
## Features
### Voice Messages
With Groq configured, voice messages are automatically transcribed.
### Server Channels
The bot works in any channel it has access to:
- Public channels
- Private channels (if bot has permission)
### Direct Messages
Users can DM the bot directly for private conversations.
## Troubleshooting
### Bot not responding
1. Check intents are enabled (especially MESSAGE CONTENT INTENT)
2. Verify the bot token is correct
3. Check `allow_from` includes your user ID
### "Missing Access" error
1. Ensure the bot has proper permissions in the channel
2. Re-invite the bot with correct permissions
### Bot appears offline
1. Make sure the gateway is running
2. Check for errors in the console output
## Advanced Configuration
### Multiple Servers
The bot can be invited to multiple servers. Use `allow_from` to control access.
### Role-Based Access
Use `allow_from` with user IDs to restrict who can use the bot.
## See Also
- [Channels Overview](README.md)
- [Gateway Command](../cli/gateway.md)
- [Troubleshooting](../../operations/troubleshooting.md)

View file

@ -0,0 +1,215 @@
# Feishu/Lark Setup
Feishu (飞书, known as Lark internationally) is an enterprise collaboration platform by ByteDance.
## Prerequisites
- A Feishu/Lark account
- Admin access to a Feishu/Lark organization (or ability to create one)
## Step 1: Create a Feishu App
1. Go to [Feishu Open Platform](https://open.feishu.cn/) (China) or [Lark Developer](https://open.larksuite.com/) (International)
2. Log in with your Feishu/Lark account
3. Click **"Create Custom App"** (创建企业自建应用)
4. Fill in the application information:
- App name (e.g., "PicoClaw Bot")
- App description
- App icon
5. Click **"Create"**
## Step 2: Get App Credentials
1. In your app dashboard, go to **"Credentials & Basic Info"** (凭证与基础信息)
2. Copy the **"App ID"**
3. Copy the **"App Secret"**
## Step 3: Configure Event Subscription
1. Go to **"Event Subscriptions"** (事件订阅)
2. Enable event subscription
3. Configure encryption (optional but recommended):
- Copy the **"Verification Token"** (验证令牌)
- Copy the **"Encrypt Key"** (加密密钥)
4. Add events to subscribe:
- **"Receive message"** (接收消息) - `im.message.receive_v1`
## Step 4: Set Permissions
1. Go to **"Permission Management"** (权限管理)
2. Request these permissions:
- `im:message` - Get and send messages
- `im:message:send_as_bot` - Send messages as bot
- `im:chat` - Get chat information
3. Wait for approval if required
## Step 5: Publish App
1. Go to **"Version Management & Release"** (版本管理与发布)
2. Create a version
3. Submit for review
4. After approval, publish to your organization
## Step 6: Configure PicoClaw
Edit `~/.picoclaw/config.json`:
```json
{
"channels": {
"feishu": {
"enabled": true,
"app_id": "cli_xxxxxxxxxxxx",
"app_secret": "xxxxxxxxxxxxxxxxxxxx",
"verification_token": "xxxxxxxx",
"encrypt_key": "xxxxxxxx",
"allow_from": []
}
}
}
```
| Option | Required | Description |
|--------|----------|-------------|
| `enabled` | Yes | Set to `true` to enable |
| `app_id` | Yes | App ID from Feishu Open Platform |
| `app_secret` | Yes | App Secret from Feishu Open Platform |
| `verification_token` | No | Verification token for event validation |
| `encrypt_key` | No | Encrypt key for event decryption |
| `allow_from` | No | Array of allowed user IDs |
## Step 7: Start the Gateway
```bash
picoclaw gateway
```
You should see:
```
Feishu channel started (websocket mode)
```
## Step 8: Test
1. Open Feishu/Lark
2. Find your bot in the organization
3. Send a message to the bot
4. The bot should respond!
## Features
### WebSocket Mode
PicoClaw uses Feishu's WebSocket connection for real-time event delivery. Benefits include:
- No need for a public webhook URL
- Instant message delivery
- Automatic reconnection
### Text Messages
The bot processes text messages and responds accordingly.
### Chat Types
The bot works in various chat types:
- One-on-one conversations (P2P)
- Group chats
- Topic-based discussions
## Troubleshooting
### Bot not responding
1. Verify app_id and app_secret are correct
2. Check that events are subscribed
3. Ensure the app is published
4. Check the gateway is running
### "Authentication failed" error
1. Verify app_id and app_secret are correct
2. Check if the app is approved and active
3. Ensure no extra whitespace in credentials
### WebSocket connection issues
1. Check your network allows WebSocket connections
2. Verify firewall allows connections to Feishu servers
3. Check logs for specific error messages
### Events not received
1. Verify event subscription is enabled
2. Check that the correct events are subscribed
3. Ensure the app has necessary permissions
### Permission errors
1. Go to Feishu Open Platform
2. Verify all required permissions are granted
3. Request additional permissions if needed
## Advanced Configuration
### Allow Specific Users
```json
{
"channels": {
"feishu": {
"enabled": true,
"app_id": "cli_xxxxxxxxxxxx",
"app_secret": "xxxxxxxxxxxxxxxxxxxx",
"verification_token": "xxxxxxxx",
"encrypt_key": "xxxxxxxx",
"allow_from": ["ou_xxxxx", "ou_yyyyy"]
}
}
}
```
### Multi-Tenant Setup
For multiple organizations, create separate apps and use separate configurations.
## Regional Differences
### Feishu (China)
- Platform: https://open.feishu.cn/
- Use for users in mainland China
- May require ICP filing for some features
### Lark (International)
- Platform: https://open.larksuite.com/
- Use for international users
- Different data centers and API endpoints
## Important Notes
### App Review
Internal enterprise apps typically don't require review, but publishing to the app store does.
### Rate Limits
Feishu has rate limits on API calls. For high-volume usage:
- Implement message batching
- Consider caching frequent queries
- Contact Feishu for higher limits
### Security
- Keep app_secret secure
- Use encrypt_key for sensitive data
- Implement proper user authorization
## See Also
- [Channels Overview](README.md)
- [Gateway Command](../cli/gateway.md)
- [Feishu Open Platform](https://open.feishu.cn/)
- [Lark Developer Documentation](https://open.larksuite.com/document/)
- [Troubleshooting](../../operations/troubleshooting.md)

View file

@ -0,0 +1,195 @@
# LINE Setup
LINE is a popular messaging app in Japan, Taiwan, Thailand, and other Asian countries.
## Prerequisites
- A LINE account
- A LINE Official Account (free tier available)
- A server accessible from the internet (for webhooks)
## Step 1: Create a LINE Official Account
1. Go to [LINE Developers Console](https://developers.line.biz/)
2. Log in with your LINE account
3. Create a new provider (or select existing)
4. Create a new channel:
- Select **"Messaging API"**
- Fill in the required information
- Click **"Create"**
## Step 2: Get Channel Credentials
1. In your channel settings, go to **"Messaging API"** tab
2. Copy the **"Channel secret"**
3. Click **"Issue"** next to **"Channel access token"**
4. Copy the **"Channel access token"**
## Step 3: Configure Webhook
LINE requires a webhook URL to receive messages. You have two options:
### Option A: Use a Tunnel (Development)
Use a service like ngrok or cloudflared:
```bash
# Using ngrok
ngrok http 18791
# Using cloudflared
cloudflared tunnel --url http://localhost:18791
```
Note the HTTPS URL (e.g., `https://abc123.ngrok.io`).
### Option B: Use a Public Server
Deploy PicoClaw on a server with a public IP and configure your domain.
## Step 4: Configure PicoClaw
Edit `~/.picoclaw/config.json`:
```json
{
"channels": {
"line": {
"enabled": true,
"channel_secret": "YOUR_CHANNEL_SECRET",
"channel_access_token": "YOUR_CHANNEL_ACCESS_TOKEN",
"webhook_host": "0.0.0.0",
"webhook_port": 18791,
"webhook_path": "/webhook/line",
"allow_from": []
}
}
}
```
| Option | Required | Description |
|--------|----------|-------------|
| `enabled` | Yes | Set to `true` to enable |
| `channel_secret` | Yes | Channel secret from LINE Developers Console |
| `channel_access_token` | Yes | Channel access token from LINE Developers Console |
| `webhook_host` | No | Host to bind webhook server (default: `0.0.0.0`) |
| `webhook_port` | No | Port for webhook server (default: `18791`) |
| `webhook_path` | No | Path for webhook endpoint (default: `/webhook/line`) |
| `allow_from` | No | Array of allowed user IDs |
## Step 5: Start the Gateway
```bash
picoclaw gateway
```
You should see:
```
LINE webhook server listening addr=0.0.0.0:18791 path=/webhook/line
LINE channel started (Webhook Mode)
```
## Step 6: Register Webhook URL
1. Go back to [LINE Developers Console](https://developers.line.biz/)
2. In your channel settings, go to **"Messaging API"** tab
3. Set the **"Webhook URL"**:
- For ngrok: `https://abc123.ngrok.io/webhook/line`
4. Click **"Verify"** to test the connection
5. Enable **"Use webhook"**
## Step 7: Test
1. Open LINE on your phone
2. Add your Official Account as a friend (scan QR code or search by ID)
3. Send a message to the bot
4. The bot should respond!
## Features
### Reply vs Push API
LINE has two message sending methods:
- **Reply API**: Free, valid for ~25 seconds after receiving a message
- **Push API**: Requires paid plan, sends messages proactively
PicoClaw automatically uses Reply API when possible and falls back to Push API.
### Group Chats
In group chats, the bot only responds when:
- Mentioned with `@BotName`
- Or @mentioned via LINE's mention feature
### Loading Indicator
PicoClaw sends a loading indicator while processing messages.
### Media Support
The bot can receive images, audio, and video files.
## Troubleshooting
### Webhook verification fails
1. Ensure the gateway is running
2. Verify the webhook URL is correct
3. Check firewall allows incoming connections
4. Verify `channel_secret` is correct
### Bot not responding
1. Check webhook is enabled in LINE Developers Console
2. Verify `channel_access_token` is valid
3. Check gateway logs for errors
### "Invalid signature" error
1. Verify `channel_secret` is correct
2. Ensure no extra whitespace in the secret
### Messages sent but no response
1. Check if Reply API timed out (> 25 seconds)
2. Consider upgrading to a paid plan for Push API
## Advanced Configuration
### Custom Webhook Path
```json
{
"channels": {
"line": {
"enabled": true,
"channel_secret": "YOUR_CHANNEL_SECRET",
"channel_access_token": "YOUR_CHANNEL_ACCESS_TOKEN",
"webhook_path": "/my-custom-webhook"
}
}
}
```
### Allow Specific Users
```json
{
"channels": {
"line": {
"enabled": true,
"channel_secret": "YOUR_CHANNEL_SECRET",
"channel_access_token": "YOUR_CHANNEL_ACCESS_TOKEN",
"allow_from": ["U1234567890abcdef", "U0987654321fedcba"]
}
}
}
```
## See Also
- [Channels Overview](README.md)
- [Gateway Command](../cli/gateway.md)
- [LINE Messaging API Documentation](https://developers.line.biz/en/docs/messaging-api/)
- [Troubleshooting](../../operations/troubleshooting.md)

View file

@ -0,0 +1,275 @@
# MaixCam Setup
MaixCam is an AI-enabled camera device that can detect and report events to PicoClaw.
## Prerequisites
- A MaixCam device
- Network connectivity between MaixCam and PicoClaw server
## Overview
MaixCam is a hardware device with AI capabilities (person detection, object recognition, etc.). It connects to PicoClaw via TCP and sends event notifications when detections occur.
## Step 1: Set Up MaixCam Device
1. Power on your MaixCam device
2. Connect it to your network (WiFi or Ethernet)
3. Configure the device to send events to your PicoClaw server
Refer to your MaixCam documentation for specific setup instructions.
## Step 2: Configure PicoClaw
Edit `~/.picoclaw/config.json`:
```json
{
"channels": {
"maixcam": {
"enabled": true,
"host": "0.0.0.0",
"port": 18790,
"allow_from": []
}
}
}
```
| Option | Required | Description |
|--------|----------|-------------|
| `enabled` | Yes | Set to `true` to enable |
| `host` | No | Host to bind TCP server (default: `0.0.0.0`) |
| `port` | No | Port for TCP server (default: `18790`) |
| `allow_from` | No | Array of allowed device identifiers |
## Step 3: Start the Gateway
```bash
picoclaw gateway
```
You should see:
```
Starting MaixCam channel server
MaixCam server listening host=0.0.0.0 port=18790
```
## Step 4: Configure MaixCam to Connect
On your MaixCam device, configure it to connect to PicoClaw:
- Server IP: Your PicoClaw server's IP address
- Server Port: `18790` (or your configured port)
## Step 5: Test
1. Trigger a detection event on your MaixCam (e.g., walk in front of the camera)
2. The AI agent will receive the detection event and can respond accordingly
## Message Format
MaixCam sends JSON messages over TCP:
### Person Detection Event
```json
{
"type": "person_detected",
"timestamp": 1708346400.123,
"data": {
"class_name": "person",
"class_id": 0,
"score": 0.95,
"x": 100,
"y": 200,
"w": 50,
"h": 100
}
}
```
### Heartbeat Event
```json
{
"type": "heartbeat",
"timestamp": 1708346400.123,
"data": {}
}
```
### Status Event
```json
{
"type": "status",
"timestamp": 1708346400.123,
"data": {
"status": "online",
"battery": 85
}
}
```
## Features
### Person Detection
When a person is detected, PicoClaw receives:
- Class name (e.g., "person")
- Confidence score
- Position (x, y)
- Bounding box size (w, h)
### Status Updates
The device can send status updates including:
- Online/offline status
- Battery level
- System health
### Command Response
PicoClaw can send commands back to the MaixCam:
```json
{
"type": "command",
"timestamp": 0,
"message": "Command from AI",
"chat_id": "default"
}
```
## Use Cases
### Security Monitoring
The AI agent can:
- Log detection events
- Send alerts to other channels
- Trigger actions based on detection
### Smart Home Integration
Connect with other smart home devices:
- Turn on lights when person detected
- Trigger recordings
- Send notifications
### Activity Logging
Track and analyze:
- Movement patterns
- Peak activity times
- Anomaly detection
## Troubleshooting
### Device not connecting
1. Verify network connectivity
2. Check firewall allows incoming connections on configured port
3. Verify MaixCam is configured with correct server IP and port
### No events received
1. Check MaixCam logs for errors
2. Verify detection features are enabled on the device
3. Check PicoClaw gateway logs for connection messages
### Connection drops frequently
1. Check network stability
2. Verify power supply to MaixCam
3. Check for interference if using WiFi
### Slow response times
1. Check network latency
2. Verify MaixCam processing is not overloaded
3. Consider reducing detection frequency
## Advanced Configuration
### Custom Port
```json
{
"channels": {
"maixcam": {
"enabled": true,
"host": "0.0.0.0",
"port": 9999
}
}
}
```
### Multiple Devices
Multiple MaixCam devices can connect to the same PicoClaw server. Each device maintains its own connection.
### With Other Channels
Combine MaixCam with other channels for notifications:
```json
{
"channels": {
"maixcam": {
"enabled": true,
"host": "0.0.0.0",
"port": 18790
},
"telegram": {
"enabled": true,
"token": "YOUR_BOT_TOKEN",
"allow_from": ["YOUR_USER_ID"]
}
}
}
```
The AI agent can then forward MaixCam alerts to Telegram.
## Example Agent Response
When MaixCam sends a person detection, you can configure your agent to respond:
```
Person detected!
Class: person
Confidence: 95.00%
Position: (100, 200)
Size: 50x100
```
The agent can then:
- Log the event to memory
- Send a notification to another channel
- Trigger additional analysis
## Technical Details
### Connection Protocol
- Transport: TCP
- Encoding: JSON (newline-delimited or continuous stream)
- Direction: Bidirectional (events from device, commands to device)
### Message Processing
1. MaixCam connects to PicoClaw TCP server
2. MaixCam sends JSON events
3. PicoClaw parses and routes events to the AI agent
4. AI agent processes and can respond with commands
## See Also
- [Channels Overview](README.md)
- [Gateway Command](../cli/gateway.md)
- [MaixCam Documentation](https://maix.sipeed.com/)
- [Troubleshooting](../../operations/troubleshooting.md)

View file

@ -0,0 +1,291 @@
# OneBot Setup
OneBot is a universal chatbot protocol that provides a standardized API for various messaging platforms.
## Prerequisites
- A OneBot-compatible implementation running
- Understanding of which platform you're connecting to (QQ, Telegram, etc.)
## Overview
OneBot (formerly CQHTTP) is a protocol specification that allows bots to communicate with various messaging platforms through a unified API. PicoClaw connects to a OneBot implementation via WebSocket.
## Supported OneBot Implementations
### For QQ
- [go-cqhttp](https://github.com/Mrs4s/go-cqhttp) - Popular Go implementation
- [Lagrange](https://github.com/LagrangeDev/Lagrange.Core) - Modern .NET implementation
- [NapCat](https://github.com/NapNeko/NapCatQQ) - Modern implementation
### For Other Platforms
- Various community implementations exist for WeChat, Telegram, etc.
## Step 1: Install a OneBot Implementation
### go-cqhttp Example
1. Download go-cqhttp from [GitHub Releases](https://github.com/Mrs4s/go-cqhttp/releases)
2. Run it once to generate config files
3. Edit `config.yml`:
```yaml
# config.yml
account:
uin: YOUR_QQ_NUMBER
password: ''
servers:
- ws:
host: 127.0.0.1
port: 3001
message:
post-format: string
```
4. Run go-cqhttp and scan the QR code to log in
## Step 2: Configure PicoClaw
Edit `~/.picoclaw/config.json`:
```json
{
"channels": {
"onebot": {
"enabled": true,
"ws_url": "ws://127.0.0.1:3001",
"access_token": "",
"reconnect_interval": 5,
"group_trigger_prefix": [],
"allow_from": []
}
}
}
```
| Option | Required | Description |
|--------|----------|-------------|
| `enabled` | Yes | Set to `true` to enable |
| `ws_url` | Yes | WebSocket URL of OneBot implementation |
| `access_token` | No | Access token for authentication |
| `reconnect_interval` | No | Reconnection interval in seconds (default: 5) |
| `group_trigger_prefix` | No | Prefixes to trigger bot in groups (e.g., `["!", "/"]`) |
| `allow_from` | No | Array of allowed user IDs |
## Step 3: Start the Gateway
```bash
picoclaw gateway
```
You should see:
```
Starting OneBot channel ws_url=ws://127.0.0.1:3001
WebSocket connected
OneBot channel started successfully
```
## Step 4: Test
### Private Messages
1. Open your messaging app (e.g., QQ)
2. Send a message to the bot account
3. The bot should respond!
### Group Messages
In group chats, the bot responds when:
- Mentioned with `@BotName`
- Message starts with a configured trigger prefix
## Features
### Voice Transcription
With Groq configured, voice messages are automatically transcribed:
```json
{
"providers": {
"groq": {
"api_key": "gsk_xxx"
}
}
}
```
### Group Trigger Prefixes
Configure prefixes to trigger the bot in groups without mentioning:
```json
{
"channels": {
"onebot": {
"enabled": true,
"ws_url": "ws://127.0.0.1:3001",
"group_trigger_prefix": ["!", "/bot"]
}
}
}
```
With this configuration:
- `!hello` triggers the bot
- `/bot hello` triggers the bot
- `hello` does not trigger the bot (unless mentioned)
### Automatic Reconnection
The bot automatically reconnects if the WebSocket connection is lost.
### Message Replies
The bot replies to messages using the original message's context.
### Emoji Reactions
In group chats, the bot adds emoji reactions to indicate processing status.
## Chat ID Format
PicoClaw uses specific chat ID formats for OneBot:
| Chat Type | Format | Example |
|-----------|--------|---------|
| Private | `private:USER_ID` | `private:123456789` |
| Group | `group:GROUP_ID` | `group:987654321` |
## Troubleshooting
### Connection refused
1. Verify your OneBot implementation is running
2. Check the ws_url is correct
3. Ensure the WebSocket server is listening
### Bot not responding
1. Check OneBot logs for errors
2. Verify the messaging account is logged in
3. Check `allow_from` includes your user ID
### "WebSocket not connected" error
1. Verify OneBot WebSocket server is running
2. Check network connectivity
3. Increase `reconnect_interval` if connection is unstable
### Group messages ignored
1. Use `@BotName` or configure `group_trigger_prefix`
2. Verify the bot has proper permissions in the group
### Voice transcription fails
1. Verify Groq API key is configured
2. Check network allows connections to Groq API
3. Check logs for specific error messages
## Advanced Configuration
### With Access Token
```json
{
"channels": {
"onebot": {
"enabled": true,
"ws_url": "ws://127.0.0.1:3001",
"access_token": "your_secure_token",
"reconnect_interval": 10
}
}
}
```
### Allow Specific Users
```json
{
"channels": {
"onebot": {
"enabled": true,
"ws_url": "ws://127.0.0.1:3001",
"allow_from": ["123456789", "987654321"]
}
}
}
```
## OneBot Configuration Examples
### go-cqhttp
```yaml
# config.yml
account:
uin: 123456789
password: ''
servers:
- ws:
host: 127.0.0.1
port: 3001
middle:
access-token: your_secure_token
message:
post-format: array
database:
leveldb:
enable: true
```
### Lagrange
```json
{
"Implementations": [
{
"Type": "ForwardWebSocket",
"Host": "127.0.0.1",
"Port": 3001,
"AccessToken": "your_secure_token"
}
]
}
```
## Important Notes
### Account Security
- Use a dedicated account for the bot
- Enable two-factor authentication
- Keep access tokens secure
### Rate Limits
Messaging platforms have rate limits. OneBot implementations typically handle this, but be aware of:
- Message sending frequency
- API call limits
- Group operation limits
### Platform Terms of Service
Using unofficial clients may violate platform terms of service. Use at your own risk.
## See Also
- [Channels Overview](README.md)
- [Gateway Command](../cli/gateway.md)
- [OneBot Specification](https://github.com/botuniverse/onebot)
- [go-cqhttp](https://github.com/Mrs4s/go-cqhttp)
- [Troubleshooting](../../operations/troubleshooting.md)

View file

@ -0,0 +1,178 @@
# QQ Setup
QQ is a popular instant messaging platform in China. PicoClaw connects via the QQ Official Bot API.
## Prerequisites
- A QQ account
- Access to [QQ Open Platform](https://bot.q.qq.com/)
## Step 1: Create a QQ Bot
1. Go to [QQ Bot Platform](https://bot.q.qq.com/)
2. Log in with your QQ account
3. Click **"Create Bot"** (创建机器人)
4. Fill in the bot information:
- Bot name
- Bot description
- Bot avatar
5. Submit for review (approval may take 1-3 days)
## Step 2: Get App Credentials
After approval:
1. Go to your bot's dashboard
2. Find **"App ID"** (AppID)
3. Find **"App Secret"** (AppSecret)
4. Copy both values
## Step 3: Configure Bot Settings
1. In the bot dashboard, go to **"Intents"** (事件订阅)
2. Enable these intents:
- **Private messages** (C2C消息)
- **Group @ messages** (群@消息)
3. Save settings
## Step 4: Configure PicoClaw
Edit `~/.picoclaw/config.json`:
```json
{
"channels": {
"qq": {
"enabled": true,
"app_id": "YOUR_APP_ID",
"app_secret": "YOUR_APP_SECRET",
"allow_from": []
}
}
}
```
| Option | Required | Description |
|--------|----------|-------------|
| `enabled` | Yes | Set to `true` to enable |
| `app_id` | Yes | App ID from QQ Bot Platform |
| `app_secret` | Yes | App Secret from QQ Bot Platform |
| `allow_from` | No | Array of allowed user IDs |
## Step 5: Start the Gateway
```bash
picoclaw gateway
```
You should see:
```
Starting QQ bot (WebSocket mode)
QQ bot started successfully
```
## Step 6: Test
### Private Messages
1. Open QQ
2. Search for your bot by name
3. Send a friend request if needed
4. Send a message to the bot
### Group Messages
1. Add the bot to a QQ group
2. Mention the bot: `@YourBotName hello`
3. The bot should respond!
## Features
### Private Messages (C2C)
Direct messages to the bot are processed automatically.
### Group @ Mentions
In group chats, the bot responds only when:
- The bot is mentioned with `@BotName`
- The message is a reply to the bot
### Automatic Token Refresh
The bot automatically refreshes access tokens as needed.
## Troubleshooting
### Bot not responding
1. Verify app_id and app_secret are correct
2. Check that intents are enabled in the QQ Bot Platform
3. Ensure the gateway is running
4. Check firewall allows WebSocket connections
### "Authentication failed" error
1. Verify app_id and app_secret are correct
2. Check if the bot is approved and active
3. Ensure no extra whitespace in credentials
### Group messages ignored
1. Ensure you're using `@BotName` to mention the bot
2. Check that "Group @ messages" intent is enabled
3. Verify the bot has proper permissions in the group
### WebSocket connection issues
1. Check your network allows WebSocket connections to QQ servers
2. Verify no firewall is blocking outgoing connections
3. Check logs for specific error messages
## Advanced Configuration
### Allow Specific Users
```json
{
"channels": {
"qq": {
"enabled": true,
"app_id": "YOUR_APP_ID",
"app_secret": "YOUR_APP_SECRET",
"allow_from": ["123456789", "987654321"]
}
}
}
```
### Multiple Guilds/Servers
The bot can be added to multiple QQ guilds. Use `allow_from` to control access across all of them.
## Important Notes
### Bot Approval
QQ bots require approval before they can be used publicly. During development, you can test with your own account.
### Rate Limits
QQ has rate limits on API calls. If you experience issues with high-volume usage, consider:
- Reducing message frequency
- Implementing message batching
- Contacting QQ for higher limits
### Regional Restrictions
QQ Bot Platform may have restrictions based on:
- Your account region
- Bot content type
- Target audience
## See Also
- [Channels Overview](README.md)
- [Gateway Command](../cli/gateway.md)
- [QQ Bot Documentation](https://bot.q.qq.com/wiki/)
- [Troubleshooting](../../operations/troubleshooting.md)

View file

@ -0,0 +1,189 @@
# Slack Setup
Slack is ideal for team collaboration and workplace automation.
## Prerequisites
- A Slack workspace with admin access (or ability to create apps)
- A Slack account
## Step 1: Create a Slack App
1. Go to [Slack API: Applications](https://api.slack.com/apps)
2. Click **"Create New App"**
3. Choose **"From scratch"**
4. Give it a name (e.g., "PicoClaw Bot")
5. Select your workspace
6. Click **"Create App"**
## Step 2: Get Bot Token
1. In your app, go to **"OAuth & Permissions"** in the left sidebar
2. Under **"Bot Token Scopes"**, add these scopes:
- `app_mentions:read` - Read messages that mention the bot
- `channels:history` - Read messages in public channels
- `chat:write` - Send messages
- `files:read` - Read files shared with the bot
`groups:history` - Read messages in private channels
- `im:history` - Read messages in direct messages
- `mpim:history` - Read messages in multi-party DMs
- `reactions:read` - Read message reactions
- `reactions:write` - Add reactions to messages
3. Click **"Install to Workspace"**
4. Copy the **"Bot User OAuth Token"** (starts with `xoxb-`)
## Step 3: Enable Socket Mode
1. Go to **"Socket Mode"** in the left sidebar
2. Enable Socket Mode
3. Click **"Generate Token"**
4. Copy the **"App-Level Token"** (starts with `xapp-`)
## Step 4: Subscribe to Events
1. Go to **"Event Subscriptions"** in the left sidebar
2. Enable events
3. Under **"Subscribe to bot events"**, add:
- `message.channels` - Messages in public channels
- `message.groups` - Messages in private channels
- `message.im` - Direct messages
- `message.mpim` - Multi-party direct messages
- `app_mention` - Bot mentions
4. Save changes
## Step 5: Get Your User ID
1. Open Slack
2. Click your profile picture (top right)
3. Click **"Profile"**
4. Click the **"..."** menu
5. Select **"Copy member ID"**
## Step 6: Configure PicoClaw
Edit `~/.picoclaw/config.json`:
```json
{
"channels": {
"slack": {
"enabled": true,
"bot_token": "xoxb-...",
"app_token": "xapp-...",
"allow_from": ["U1234567890"]
}
}
}
```
| Option | Required | Description |
|--------|----------|-------------|
| `enabled` | Yes | Set to `true` to enable |
| `bot_token` | Yes | Bot User OAuth Token (starts with `xoxb-`) |
| `app_token` | Yes | App-Level Token for Socket Mode (starts with `xapp-`) |
| `allow_from` | No | Array of allowed user IDs |
## Step 7: Start the Gateway
```bash
picoclaw gateway
```
You should see:
```
Channels enabled: slack
Slack bot connected
Slack channel started (Socket Mode)
```
## Step 8: Test
1. Open Slack
2. Invite the bot to a channel: `/invite @PicoClaw Bot`
3. Send a message mentioning the bot: `@PicoClaw Bot hello`
4. The bot should respond!
## Features
### Voice Messages
With Groq configured, voice messages are automatically transcribed:
```json
{
"providers": {
"groq": {
"api_key": "gsk_xxx"
}
}
}
```
### Direct Messages
Users can DM the bot directly for private conversations.
### Thread Replies
The bot maintains thread context - replies in threads stay in threads.
### Reactions
The bot adds a "eyes" reaction when processing a message and a "white_check_mark" when done.
## Troubleshooting
### Bot not responding
1. Verify Socket Mode is enabled
2. Check both bot_token and app_token are correct
3. Ensure events are subscribed
4. Check `allow_from` includes your user ID
### "not_authed" or "invalid_auth" error
1. Re-install the app to your workspace
2. Verify tokens are correct and not expired
### Bot can't read messages
1. Ensure the bot is invited to the channel
2. Check that required OAuth scopes are added
3. Re-install the app after adding scopes
### Socket Mode connection issues
1. Verify your network allows WebSocket connections
2. Check the app_token is an App-Level Token (starts with `xapp-`)
## Advanced Configuration
### Multiple Users
```json
{
"channels": {
"slack": {
"enabled": true,
"bot_token": "xoxb-...",
"app_token": "xapp-...",
"allow_from": ["U1234567890", "U0987654321"]
}
}
}
```
### Slash Commands
To add slash commands:
1. Go to **"Slash Commands"** in your app
2. Create a new command (e.g., `/picoclaw`)
3. Set the request URL (not needed for Socket Mode)
4. Install the app to update
## See Also
- [Channels Overview](README.md)
- [Gateway Command](../cli/gateway.md)
- [Troubleshooting](../../operations/troubleshooting.md)

View file

@ -0,0 +1,163 @@
# Telegram Setup
Telegram is one of the easiest platforms to set up and is recommended for personal use.
## Prerequisites
- A Telegram account
- Access to @BotFather on Telegram
## Step 1: Create a Bot
1. Open Telegram and search for `@BotFather`
2. Send `/newbot`
3. Follow the prompts:
- Choose a name for your bot (e.g., "My PicoClaw Bot")
- Choose a username (must end in `bot`, e.g., `mypicoclaw_bot`)
4. Copy the **bot token** (looks like `123456789:ABCdefGHIjklMNOpqrsTUVwxyz`)
## Step 2: Get Your User ID
1. Search for `@userinfobot` on Telegram
2. Send any message
3. Copy your **User ID** (a number like `123456789`)
## Step 3: Configure PicoClaw
Edit `~/.picoclaw/config.json`:
```json
{
"channels": {
"telegram": {
"enabled": true,
"token": "123456789:ABCdefGHIjklMNOpqrsTUVwxyz",
"allow_from": ["123456789"]
}
}
}
```
| Option | Required | Description |
|--------|----------|-------------|
| `enabled` | Yes | Set to `true` to enable |
| `token` | Yes | Bot token from @BotFather |
| `proxy` | No | Proxy URL if needed |
| `allow_from` | No | Array of allowed user IDs |
## Step 4: Start the Gateway
```bash
picoclaw gateway
```
You should see:
```
✓ Channels enabled: telegram
✓ Gateway started on 0.0.0.0:18790
```
## Step 5: Test
1. Open Telegram
2. Find your bot (search for the username)
3. Send a message
4. The bot should respond!
## Features
### Voice Messages
With Groq configured, voice messages are automatically transcribed:
```json
{
"providers": {
"groq": {
"api_key": "gsk_xxx"
}
}
}
```
### Group Chats
The bot works in group chats:
- Mention the bot with `@your_bot_name message`
- Or reply to the bot's messages
### Commands
Telegram supports bot commands:
| Command | Description |
|---------|-------------|
| `/start` | Start interacting with the bot |
| `/help` | Show help message |
| `/reset` | Reset conversation session |
## Troubleshooting
### Bot not responding
1. Check the gateway is running: `picoclaw gateway`
2. Verify your user ID is in `allow_from`
3. Check the bot token is correct
### "Conflict: terminated by other getUpdates"
This means another instance is using the bot token:
1. Stop other running instances
2. Make sure only one `picoclaw gateway` is running
### Proxy issues
If you need a proxy:
```json
{
"channels": {
"telegram": {
"enabled": true,
"token": "YOUR_TOKEN",
"proxy": "http://127.0.0.1:7890"
}
}
}
```
## Advanced Configuration
### Allow Multiple Users
```json
{
"channels": {
"telegram": {
"enabled": true,
"token": "YOUR_TOKEN",
"allow_from": ["123456789", "987654321", "111222333"]
}
}
}
```
### Allow All Users (Not Recommended)
```json
{
"channels": {
"telegram": {
"enabled": true,
"token": "YOUR_TOKEN",
"allow_from": []
}
}
}
```
## See Also
- [Channels Overview](README.md)
- [Gateway Command](../cli/gateway.md)
- [Troubleshooting](../../operations/troubleshooting.md)

View file

@ -0,0 +1,228 @@
# WhatsApp Setup
WhatsApp is the world's most popular messaging app. PicoClaw connects via a bridge service.
## Prerequisites
- A WhatsApp account
- A WhatsApp bridge service (e.g., mautrix-whatsapp, whatsapp-web.js)
## Overview
PicoClaw requires a bridge service to connect to WhatsApp because WhatsApp does not provide a direct bot API for personal accounts. The bridge acts as a middleware between WhatsApp and PicoClaw.
## Step 1: Set Up a WhatsApp Bridge
### Option A: mautrix-whatsapp (Recommended)
[mautrix-whatsapp](https://github.com/mautrix/whatsapp) is a Matrix-WhatsApp bridge that can be adapted for PicoClaw.
### Option B: Custom Bridge
You can create a custom WebSocket bridge using libraries like:
- [whatsapp-web.js](https://github.com/pedroslopez/whatsapp-web.js) (Node.js)
- [Baileys](https://github.com/WhiskeySockets/Baileys) (Node.js)
The bridge should:
1. Connect to WhatsApp
2. Expose a WebSocket server
3. Forward messages between WhatsApp and PicoClaw
## Step 2: Bridge Protocol
Your bridge should communicate with PicoClaw via WebSocket using this message format:
### Incoming Messages (to PicoClaw)
```json
{
"type": "message",
"from": "sender_phone_number",
"chat": "chat_id",
"content": "message text",
"id": "message_id",
"from_name": "Sender Name",
"media": []
}
```
### Outgoing Messages (from PicoClaw)
```json
{
"type": "message",
"to": "chat_id",
"content": "response text"
}
```
## Step 3: Configure PicoClaw
Edit `~/.picoclaw/config.json`:
```json
{
"channels": {
"whatsapp": {
"enabled": true,
"bridge_url": "ws://localhost:3001",
"allow_from": []
}
}
}
```
| Option | Required | Description |
|--------|----------|-------------|
| `enabled` | Yes | Set to `true` to enable |
| `bridge_url` | Yes | WebSocket URL of your bridge service |
| `allow_from` | No | Array of allowed phone numbers |
## Step 4: Start the Gateway
```bash
picoclaw gateway
```
You should see:
```
Starting WhatsApp channel connecting to ws://localhost:3001...
WhatsApp channel connected
```
## Step 5: Test
1. Open WhatsApp on your phone
2. Send a message to the connected account
3. The bot should respond!
## Features
### Media Support
The bridge can forward media files:
```json
{
"type": "message",
"from": "+1234567890",
"chat": "+1234567890",
"content": "Check this image",
"media": ["/path/to/image.jpg"]
}
```
### Group Chats
Group chat support depends on your bridge implementation.
### Message Metadata
Additional metadata can be included:
```json
{
"type": "message",
"from": "+1234567890",
"chat": "group_id@g.us",
"content": "Hello group!",
"id": "msg_123",
"from_name": "John Doe"
}
```
## Troubleshooting
### Connection refused
1. Verify your bridge service is running
2. Check the bridge_url is correct
3. Ensure the WebSocket server is listening
### Messages not received
1. Check bridge logs for errors
2. Verify WhatsApp connection is active
3. Ensure the bridge is forwarding messages correctly
### Messages not sent
1. Check PicoClaw logs for errors
2. Verify the bridge is handling outgoing messages
3. Check WhatsApp session is valid
### Bridge disconnects frequently
1. Check network stability
2. Verify WhatsApp session is persistent
3. Consider implementing reconnection logic in your bridge
## Bridge Implementation Example
Here's a simple example using Node.js with whatsapp-web.js:
```javascript
const { Client, LocalAuth } = require('whatsapp-web.js');
const WebSocket = require('ws');
// WhatsApp client
const waClient = new Client({
authStrategy: new LocalAuth()
});
// WebSocket server for PicoClaw
const wss = new WebSocket.Server({ port: 3001 });
let picoclawConnection = null;
wss.on('connection', (ws) => {
picoclawConnection = ws;
console.log('PicoClaw connected');
ws.on('message', (data) => {
const msg = JSON.parse(data);
if (msg.type === 'message') {
// Send to WhatsApp
waClient.sendMessage(msg.to, msg.content);
}
});
});
// Forward WhatsApp messages to PicoClaw
waClient.on('message', (msg) => {
if (picoclawConnection) {
picoclawConnection.send(JSON.stringify({
type: 'message',
from: msg.from,
chat: msg.from,
content: msg.body,
id: msg.id._serialized,
from_name: msg._data.notifyName
}));
}
});
waClient.initialize();
```
## Important Notes
### WhatsApp Terms of Service
Using unofficial WhatsApp clients may violate WhatsApp's Terms of Service. Use at your own risk.
### Business API
For production use, consider the official [WhatsApp Business API](https://business.whatsapp.com/).
### Session Persistence
Ensure your bridge properly saves and restores WhatsApp sessions to avoid repeated QR code scans.
## See Also
- [Channels Overview](README.md)
- [Gateway Command](../cli/gateway.md)
- [mautrix-whatsapp](https://github.com/mautrix/whatsapp)
- [whatsapp-web.js](https://github.com/pedroslopez/whatsapp-web.js)
- [Troubleshooting](../../operations/troubleshooting.md)

View file

@ -0,0 +1,328 @@
# CLI Reference
Complete reference for all PicoClaw command-line commands.
## Global Commands
### picoclaw onboard
Initialize configuration and workspace.
```bash
picoclaw onboard
```
This command:
- Creates `~/.picoclaw/config.json` with default settings
- Creates `~/.picoclaw/workspace/` directory
- Copies default workspace templates (AGENT.md, IDENTITY.md, etc.)
### picoclaw agent
Interact with the agent directly.
```bash
# Send a single message
picoclaw agent -m "What is 2+2?"
# Interactive mode
picoclaw agent
# With debug logging
picoclaw agent --debug -m "Hello"
# With specific session
picoclaw agent -s "my-session" -m "Continue our conversation"
```
| Flag | Short | Description |
|------|-------|-------------|
| `--message` | `-m` | Send a single message and exit |
| `--session` | `-s` | Session key (default: `cli:default`) |
| `--debug` | `-d` | Enable debug logging |
**Interactive Mode Commands:**
| Command | Description |
|---------|-------------|
| `exit` | Exit interactive mode |
| `quit` | Exit interactive mode |
| `Ctrl+C` | Exit interactive mode |
### picoclaw gateway
Start the gateway for all enabled channels.
```bash
# Start gateway
picoclaw gateway
# With debug logging
picoclaw gateway --debug
```
| Flag | Short | Description |
|------|-------|-------------|
| `--debug` | `-d` | Enable debug logging |
The gateway:
- Starts all enabled channels (Telegram, Discord, etc.)
- Starts the heartbeat service
- Starts the cron service
- Starts health endpoints at `http://host:port/health` and `/ready`
### picoclaw status
Show system status.
```bash
picoclaw status
```
Displays:
- Version and build info
- Config file location
- Workspace location
- Configured API keys status
- OAuth authentication status
### picoclaw version
Show version information.
```bash
picoclaw version
# or
picoclaw -v
picoclaw --version
```
## Authentication Commands
### picoclaw auth login
Login via OAuth or paste token.
```bash
# Login with OAuth (opens browser)
picoclaw auth login --provider openai
# Login with device code (headless)
picoclaw auth login --provider openai --device-code
# Login with token paste
picoclaw auth login --provider anthropic
```
| Flag | Short | Description |
|------|-------|-------------|
| `--provider` | `-p` | Provider name (openai, anthropic) |
| `--device-code` | | Use device code flow for headless environments |
### picoclaw auth logout
Remove stored credentials.
```bash
# Logout from specific provider
picoclaw auth logout --provider openai
# Logout from all providers
picoclaw auth logout
```
### picoclaw auth status
Show current authentication status.
```bash
picoclaw auth status
```
## Cron Commands
### picoclaw cron list
List all scheduled jobs.
```bash
picoclaw cron list
```
### picoclaw cron add
Add a new scheduled job.
```bash
# Every 2 hours (7200 seconds)
picoclaw cron add -n "Check weather" -m "Check weather in Beijing" -e 7200
# With cron expression (daily at 9am)
picoclaw cron add -n "Morning report" -m "Give me a morning report" -c "0 9 * * *"
# Deliver response to channel
picoclaw cron add -n "Reminder" -m "Time for a break!" -e 3600 -d --to "123456789" --channel "telegram"
```
| Flag | Short | Description |
|------|-------|-------------|
| `--name` | `-n` | Job name (required) |
| `--message` | `-m` | Message for agent (required) |
| `--every` | `-e` | Run every N seconds |
| `--cron` | `-c` | Cron expression |
| `--deliver` | `-d` | Deliver response to channel |
| `--to` | | Recipient for delivery |
| `--channel` | | Channel for delivery |
### picoclaw cron remove
Remove a scheduled job.
```bash
picoclaw cron remove <job_id>
```
### picoclaw cron enable
Enable a disabled job.
```bash
picoclaw cron enable <job_id>
```
### picoclaw cron disable
Disable a job without removing it.
```bash
picoclaw cron disable <job_id>
```
## Skills Commands
### picoclaw skills list
List installed skills.
```bash
picoclaw skills list
```
### picoclaw skills install
Install a skill from GitHub.
```bash
picoclaw skills install sipeed/picoclaw-skills/weather
```
### picoclaw skills remove
Remove an installed skill.
```bash
picoclaw skills remove weather
```
### picoclaw skills install-builtin
Install all builtin skills to workspace.
```bash
picoclaw skills install-builtin
```
### picoclaw skills list-builtin
List available builtin skills.
```bash
picoclaw skills list-builtin
```
### picoclaw skills search
Search for available skills.
```bash
picoclaw skills search
```
### picoclaw skills show
Show skill details.
```bash
picoclaw skills show weather
```
## Migration Commands
### picoclaw migrate
Migrate from OpenClaw to PicoClaw.
```bash
# Detect and migrate
picoclaw migrate
# Preview changes
picoclaw migrate --dry-run
# Re-sync workspace files
picoclaw migrate --refresh
# Migrate without confirmation
picoclaw migrate --force
# Only migrate config
picoclaw migrate --config-only
# Only migrate workspace
picoclaw migrate --workspace-only
# Override directories
picoclaw migrate --openclaw-home /path/to/openclaw --picoclaw-home /path/to/picoclaw
```
| Flag | Description |
|------|-------------|
| `--dry-run` | Show what would be migrated without making changes |
| `--refresh` | Re-sync workspace files from OpenClaw |
| `--config-only` | Only migrate config, skip workspace |
| `--workspace-only` | Only migrate workspace files, skip config |
| `--force` | Skip confirmation prompts |
| `--openclaw-home` | Override OpenClaw home directory |
| `--picoclaw-home` | Override PicoClaw home directory |
## Command Summary
| Command | Description |
|---------|-------------|
| `onboard` | Initialize configuration and workspace |
| `agent` | Interact with agent directly |
| `gateway` | Start gateway for all channels |
| `status` | Show system status |
| `version` | Show version information |
| `auth login` | Login via OAuth or token |
| `auth logout` | Remove stored credentials |
| `auth status` | Show authentication status |
| `cron list` | List scheduled jobs |
| `cron add` | Add a scheduled job |
| `cron remove` | Remove a job |
| `cron enable` | Enable a job |
| `cron disable` | Disable a job |
| `skills list` | List installed skills |
| `skills install` | Install a skill |
| `skills remove` | Remove a skill |
| `skills install-builtin` | Install builtin skills |
| `skills list-builtin` | List builtin skills |
| `skills search` | Search for skills |
| `skills show` | Show skill details |
| `migrate` | Migrate from OpenClaw |
## See Also
- [Configuration Reference](../configuration/config-file.md) - Complete configuration options
- [Quick Start](../getting-started/quick-start.md) - Get started quickly
- [Troubleshooting](../operations/troubleshooting.md) - Common issues and solutions

View file

@ -0,0 +1,114 @@
# picoclaw agent
Interact with the AI agent directly from the command line.
## Usage
```bash
# One-shot message
picoclaw agent -m "Your message here"
# Interactive mode
picoclaw agent
# With debug logging
picoclaw agent --debug -m "Hello"
# With specific session
picoclaw agent -s "my-session" -m "Continue our chat"
```
## Options
| Flag | Short | Default | Description |
|------|-------|---------|-------------|
| `--message` | `-m` | - | Send a single message and exit |
| `--session` | `-s` | `cli:default` | Session key for conversation history |
| `--debug` | `-d` | `false` | Enable debug logging |
## Modes
### One-Shot Mode
Send a single message and receive a response:
```bash
picoclaw agent -m "What is 2+2?"
```
Output:
```
🦞 2 + 2 equals 4.
```
### Interactive Mode
Start a continuous chat session:
```bash
picoclaw agent
```
```
🦞 Interactive mode (Ctrl+C to exit)
🦞 You: Hello!
🦞 Hello! How can I help you today?
🦞 You: Tell me a joke
🦞 Why don't scientists trust atoms? Because they make up everything!
🦞 You: exit
Goodbye!
```
### Debug Mode
See detailed processing information:
```bash
picoclaw agent --debug -m "Hello"
```
Debug output includes:
- LLM API requests
- Tool invocations
- Response parsing
- Timing information
## Sessions
Sessions maintain conversation history:
```bash
# Start a new session
picoclaw agent -s "work-project" -m "I'm starting a new project"
# Continue the same session
picoclaw agent -s "work-project" -m "What should we do next?"
```
Sessions are stored in `~/.picoclaw/workspace/sessions/`.
## Examples
```bash
# Quick question
picoclaw agent -m "What's the capital of France?"
# Code assistance
picoclaw agent -m "Write a Python function to reverse a string"
# With web search
picoclaw agent -m "Search for the latest news about AI and summarize"
# Continue previous conversation
picoclaw agent -s "morning-standup" -m "What did we discuss yesterday?"
```
## See Also
- [First Chat](../../getting-started/first-chat.md)
- [CLI Reference](../cli-reference.md)

140
docs/user-guide/cli/auth.md Normal file
View file

@ -0,0 +1,140 @@
# picoclaw auth
Manage authentication for LLM providers.
## Usage
```bash
# Login
picoclaw auth login --provider <name> [--device-code]
# Logout
picoclaw auth logout [--provider <name>]
# Status
picoclaw auth status
```
## Subcommands
### auth login
Authenticate with a provider.
```bash
# Login via OAuth (opens browser)
picoclaw auth login --provider openai
# Login via device code (headless)
picoclaw auth login --provider openai --device-code
# Login with token (Anthropic)
picoclaw auth login --provider anthropic
```
| Flag | Short | Description |
|------|-------|-------------|
| `--provider` | `-p` | Provider name (openai, anthropic) |
| `--device-code` | | Use device code flow for headless environments |
**Supported Providers:**
| Provider | Auth Methods |
|----------|-------------|
| `openai` | OAuth, device code |
| `anthropic` | Token paste |
### auth logout
Remove stored credentials.
```bash
# Logout from specific provider
picoclaw auth logout --provider openai
# Logout from all providers
picoclaw auth logout
```
### auth status
Show current authentication status.
```bash
picoclaw auth status
```
Output:
```
Authenticated Providers:
------------------------
openai:
Method: oauth
Status: active
Account: user@example.com
Expires: 2025-03-01 12:00
anthropic:
Method: token
Status: active
```
## When to Use OAuth vs API Key
**Use OAuth/Token when:**
- You don't want to manage API keys
- You want automatic token refresh
- Using provider-specific features
**Use API Key when:**
- Simpler setup preferred
- Using multiple providers
- Server/automated environments
## Configuration
After login, set the auth method in config:
```json
{
"providers": {
"openai": {
"auth_method": "oauth"
},
"anthropic": {
"auth_method": "token"
}
}
}
```
## Credential Storage
Credentials are stored in:
```
~/.picoclaw/credentials.json
```
This file contains sensitive tokens and should be protected.
## Examples
```bash
# Login to OpenAI
picoclaw auth login --provider openai
# Check status
picoclaw auth status
# If token expired, re-login
picoclaw auth login --provider openai
# Switch to API key instead
picoclaw auth logout --provider openai
# Then add api_key to config.json
```
## See Also
- [CLI Reference](../cli-reference.md)
- [Configuration](../../configuration/config-file.md)
- [OpenAI Provider](../providers/openai.md)

177
docs/user-guide/cli/cron.md Normal file
View file

@ -0,0 +1,177 @@
# picoclaw cron
Manage scheduled tasks and reminders.
## Usage
```bash
# List jobs
picoclaw cron list
# Add job
picoclaw cron add -n "name" -m "message" (-e <seconds> | -c <cron>)
# Remove job
picoclaw cron remove <job_id>
# Enable/disable
picoclaw cron enable <job_id>
picoclaw cron disable <job_id>
```
## Subcommands
### cron list
List all scheduled jobs.
```bash
picoclaw cron list
```
Output:
```
Scheduled Jobs:
----------------
Weather Check (abc123)
Schedule: every 3600s
Status: enabled
Next run: 2025-02-20 15:00
Morning Report (def456)
Schedule: 0 9 * * *
Status: enabled
Next run: 2025-02-21 09:00
```
### cron add
Add a new scheduled job.
```bash
# Every 2 hours (7200 seconds)
picoclaw cron add -n "Check weather" -m "Check weather in Beijing" -e 7200
# With cron expression (daily at 9am)
picoclaw cron add -n "Morning report" -m "Give me a morning report" -c "0 9 * * *"
# Deliver response to channel
picoclaw cron add -n "Reminder" -m "Time for a break!" -e 3600 -d --to "123456789" --channel "telegram"
```
| Flag | Short | Description |
|------|-------|-------------|
| `--name` | `-n` | Job name (required) |
| `--message` | `-m` | Message for the agent (required) |
| `--every` | `-e` | Run every N seconds |
| `--cron` | `-c` | Cron expression |
| `--deliver` | `-d` | Deliver response to channel |
| `--to` | | Recipient ID for delivery |
| `--channel` | | Channel name for delivery |
**Schedule Types:**
| Type | Flag | Example |
|------|------|---------|
| Interval | `-e 3600` | Every hour |
| Cron | `-c "0 9 * * *"` | Daily at 9am |
### cron remove
Remove a scheduled job.
```bash
picoclaw cron remove <job_id>
```
### cron enable / cron disable
Enable or disable a job without removing it.
```bash
picoclaw cron enable <job_id>
picoclaw cron disable <job_id>
```
## Cron Expressions
Standard 5-field cron format:
```
┌───────────── minute (0 - 59)
│ ┌───────────── hour (0 - 23)
│ │ ┌───────────── day of month (1 - 31)
│ │ │ ┌───────────── month (1 - 12)
│ │ │ │ ┌───────────── day of week (0 - 6, Sunday = 0)
│ │ │ │ │
* * * * *
```
**Examples:**
| Expression | Meaning |
|------------|---------|
| `0 9 * * *` | Every day at 9:00 AM |
| `0 */2 * * *` | Every 2 hours |
| `30 8 * * 1-5` | Weekdays at 8:30 AM |
| `0 0 * * 0` | Every Sunday at midnight |
| `0 9 1 * *` | First day of month at 9:00 AM |
## Storage
Jobs are stored in:
```
~/.picoclaw/workspace/cron/jobs.json
```
## Configuration
Configure timeout in `~/.picoclaw/config.json`:
```json
{
"tools": {
"cron": {
"exec_timeout_minutes": 5
}
}
}
```
## Job Delivery
When `--deliver` is set, the agent's response is sent to the specified channel:
```bash
# Send reminder to Telegram user
picoclaw cron add -n "Standup" -m "Time for standup!" \
-c "0 10 * * 1-5" -d --to "123456789" --channel "telegram"
```
## Examples
```bash
# Daily weather report
picoclaw cron add -n "Weather" -m "What's the weather today?" -c "0 7 * * *"
# Hourly reminder
picoclaw cron add -n "Hydrate" -m "Drink water!" -e 3600
# Weekly summary
picoclaw cron add -n "Weekly" -m "Summarize what I did this week" -c "0 17 * * 5"
# List all jobs
picoclaw cron list
# Disable a job
picoclaw cron disable abc123
# Remove a job
picoclaw cron remove abc123
```
## See Also
- [Heartbeat Tasks](../workspace/heartbeat-tasks.md)
- [Cron Tool](../tools/cron.md)
- [CLI Reference](../cli-reference.md)

View file

@ -0,0 +1,121 @@
# picoclaw gateway
Start the gateway for all enabled chat channels.
## Usage
```bash
# Start gateway
picoclaw gateway
# With debug logging
picoclaw gateway --debug
```
## Options
| Flag | Short | Description |
|------|-------|-------------|
| `--debug` | `-d` | Enable debug logging |
## Description
The gateway command starts PicoClaw in server mode, enabling:
1. **Chat Channels** - Telegram, Discord, Slack, etc.
2. **Heartbeat Service** - Periodic task execution
3. **Cron Service** - Scheduled jobs
4. **Device Monitoring** - USB device events (Linux)
5. **Health Endpoints** - `/health` and `/ready`
## What It Starts
```
✓ Channels enabled: telegram, discord
✓ Gateway started on 0.0.0.0:18790
Press Ctrl+C to stop
✓ Cron service started
✓ Heartbeat service started
✓ Health endpoints available at http://0.0.0.0:18790/health and /ready
```
## Configuration
Enable channels in `~/.picoclaw/config.json`:
```json
{
"channels": {
"telegram": {
"enabled": true,
"token": "YOUR_BOT_TOKEN",
"allow_from": ["YOUR_USER_ID"]
},
"discord": {
"enabled": true,
"token": "YOUR_BOT_TOKEN"
}
}
}
```
## Gateway Settings
Configure in `~/.picoclaw/config.json`:
```json
{
"gateway": {
"host": "0.0.0.0",
"port": 18790
}
}
```
## Health Endpoints
| Endpoint | Purpose |
|----------|---------|
| `/health` | Liveness check |
| `/ready` | Readiness check |
```bash
curl http://localhost:18790/health
# OK
curl http://localhost:18790/ready
# OK
```
## Stopping
Press `Ctrl+C` to stop the gateway gracefully:
```
^C
Shutting down...
✓ Gateway stopped
```
## Running as a Service
For production, run as a systemd service. See [Systemd Deployment](../../deployment/systemd.md).
## Examples
```bash
# Start with Telegram and Discord
picoclaw gateway
# Debug mode for troubleshooting
picoclaw gateway --debug
# Run in background
nohup picoclaw gateway > picoclaw.log 2>&1 &
```
## See Also
- [Channels Guide](../channels/README.md)
- [Systemd Deployment](../../deployment/systemd.md)
- [Health Endpoints](../../operations/health-endpoints.md)

View file

@ -0,0 +1,107 @@
# picoclaw migrate
Migrate from OpenClaw to PicoClaw.
## Usage
```bash
# Detect and migrate
picoclaw migrate
# Preview changes
picoclaw migrate --dry-run
# Full options
picoclaw migrate [options]
```
## Options
| Flag | Description |
|------|-------------|
| `--dry-run` | Show what would be migrated without making changes |
| `--refresh` | Re-sync workspace files from OpenClaw |
| `--config-only` | Only migrate config, skip workspace files |
| `--workspace-only` | Only migrate workspace files, skip config |
| `--force` | Skip confirmation prompts |
| `--openclaw-home` | Override OpenClaw home directory (default: ~/.openclaw) |
| `--picoclaw-home` | Override PicoClaw home directory (default: ~/.picoclaw) |
## Description
The migrate command helps transition from OpenClaw to PicoClaw by:
1. Detecting existing OpenClaw installation
2. Converting configuration to PicoClaw format
3. Copying workspace files (AGENT.md, MEMORY.md, etc.)
4. Preserving session history
## Examples
### Basic Migration
```bash
# Run migration
picoclaw migrate
# Output shows what will be migrated
OpenClaw detected at ~/.openclaw
Migrating to ~/.picoclaw...
✓ Config migrated
✓ Workspace files copied
✓ Sessions preserved
Migration complete!
```
### Preview Changes
```bash
picoclaw migrate --dry-run
```
### Re-sync Workspace
```bash
# If you updated OpenClaw workspace, re-sync
picoclaw migrate --refresh
```
### Partial Migration
```bash
# Only migrate config
picoclaw migrate --config-only
# Only migrate workspace
picoclaw migrate --workspace-only
```
### Custom Directories
```bash
picoclaw migrate --openclaw-home /path/to/openclaw --picoclaw-home /path/to/picoclaw
```
## What Gets Migrated
| OpenClaw | PicoClaw |
|----------|----------|
| `~/.openclaw/config.json` | `~/.picoclaw/config.json` |
| `~/.openclaw/workspace/AGENT.md` | `~/.picoclaw/workspace/AGENT.md` |
| `~/.openclaw/workspace/IDENTITY.md` | `~/.picoclaw/workspace/IDENTITY.md` |
| `~/.openclaw/workspace/MEMORY.md` | `~/.picoclaw/workspace/MEMORY.md` |
| `~/.openclaw/workspace/HEARTBEAT.md` | `~/.picoclaw/workspace/HEARTBEAT.md` |
| Sessions | Sessions |
## After Migration
1. Review `~/.picoclaw/config.json`
2. Update any provider API keys
3. Test with `picoclaw agent -m "Hello"`
4. Start gateway with `picoclaw gateway`
## See Also
- [Installation](../../getting-started/installation.md)
- [Configuration](../../configuration/config-file.md)
- [OpenClaw Migration Guide](../../migration/openclaw-migration.md)

View file

@ -0,0 +1,63 @@
# picoclaw onboard
Initialize PicoClaw configuration and workspace.
## Usage
```bash
picoclaw onboard
```
## Description
The `onboard` command sets up PicoClaw for first-time use by:
1. Creating the configuration directory at `~/.picoclaw/`
2. Generating `~/.picoclaw/config.json` with default settings
3. Creating the workspace directory at `~/.picoclaw/workspace/`
4. Copying default templates (AGENT.md, IDENTITY.md, etc.)
## What It Creates
```
~/.picoclaw/
├── config.json # Main configuration file
└── workspace/
├── sessions/ # Conversation history
├── memory/ # Long-term memory
├── cron/ # Scheduled jobs
├── skills/ # Custom skills
├── AGENT.md # Agent behavior guide
├── IDENTITY.md # Agent identity
├── SOUL.md # Agent personality
├── USER.md # User preferences
└── HEARTBEAT.md # Periodic tasks
```
## Example
```bash
$ picoclaw onboard
Config already exists at /home/user/.picoclaw/config.json
Overwrite? (y/n): y
🦞 picoclaw is ready!
Next steps:
1. Add your API key to /home/user/.picoclaw/config.json
Get one at: https://openrouter.ai/keys
2. Chat: picoclaw agent -m "Hello!"
```
## Next Steps
After running onboard:
1. Edit `~/.picoclaw/config.json` and add your API key
2. Run `picoclaw agent -m "Hello!"` to test
## See Also
- [Quick Start](../../getting-started/quick-start.md)
- [Configuration Reference](../../configuration/config-file.md)

View file

@ -0,0 +1,159 @@
# picoclaw skills
Manage skills - specialized capabilities for the agent.
## Usage
```bash
# List installed skills
picoclaw skills list
# Install from GitHub
picoclaw skills install <repo>
# Remove a skill
picoclaw skills remove <name>
# Install builtin skills
picoclaw skills install-builtin
# List builtin skills
picoclaw skills list-builtin
# Search for skills
picoclaw skills search
# Show skill details
picoclaw skills show <name>
```
## Subcommands
### skills list
List all installed skills.
```bash
picoclaw skills list
```
Output:
```
Installed Skills:
------------------
✓ weather (workspace)
Get weather information for any location
✓ news (builtin)
Fetch latest news headlines
✓ calculator (builtin)
Perform calculations
```
### skills install
Install a skill from GitHub.
```bash
picoclaw skills install sipeed/picoclaw-skills/weather
```
### skills remove
Remove an installed skill.
```bash
picoclaw skills remove weather
```
### skills install-builtin
Copy all builtin skills to your workspace.
```bash
picoclaw skills install-builtin
```
### skills list-builtin
List available builtin skills.
```bash
picoclaw skills list-builtin
```
Output:
```
Available Builtin Skills:
-----------------------
✓ weather
Get weather information
✓ news
Get latest news headlines
✓ stock
Check stock prices
✓ calculator
Perform mathematical calculations
```
### skills search
Search for available skills online.
```bash
picoclaw skills search
```
### skills show
Show details of a specific skill.
```bash
picoclaw skills show weather
```
## Skill Locations
Skills are loaded from (in order):
1. `~/.picoclaw/workspace/skills/` - Workspace skills
2. `~/.picoclaw/skills/` - Global skills
3. `~/.picoclaw/picoclaw/skills/` - Builtin skills
## Skill Structure
A skill is a directory containing `SKILL.md`:
```
weather/
├── SKILL.md # Skill definition
└── (optional files)
```
## Creating Skills
See [Creating Skills](../skills/creating-skills.md) for how to create custom skills.
## Examples
```bash
# Install a skill
picoclaw skills install sipeed/picoclaw-skills/weather
# List what's installed
picoclaw skills list
# Install all builtin skills
picoclaw skills install-builtin
# Show skill content
picoclaw skills show weather
# Remove a skill
picoclaw skills remove weather
```
## See Also
- [Skills Overview](../skills/README.md)
- [Creating Skills](../skills/creating-skills.md)
- [CLI Reference](../cli-reference.md)

View file

@ -0,0 +1,62 @@
# picoclaw status
Show PicoClaw system status and configuration.
## Usage
```bash
picoclaw status
```
## Description
The `status` command displays:
- Version and build information
- Configuration file location
- Workspace location
- API key configuration status
- OAuth authentication status
## Example Output
```
🦞 picoclaw Status
Version: 0.1.1 (git: abc123)
Config: /home/user/.picoclaw/config.json ✓
Workspace: /home/user/.picoclaw/workspace ✓
Model: anthropic/claude-opus-4-5
OpenRouter API: ✓
Anthropic API: not set
OpenAI API: ✓
Gemini API: not set
Zhipu API: not set
Groq API: ✓
vLLM/Local: not set
OAuth/Token Auth:
openai (oauth): active
anthropic (token): needs refresh
```
## Status Indicators
| Symbol | Meaning |
|--------|---------|
| ✓ | Configured and available |
| ✗ | Not configured or not found |
| `active` | OAuth token is valid |
| `expired` | OAuth token has expired |
| `needs refresh` | OAuth token should be refreshed |
## Use Cases
1. **Verify configuration** - Check API keys are set
2. **Debug issues** - Confirm config file is found
3. **Check authentication** - Verify OAuth tokens
## See Also
- [CLI Reference](../cli-reference.md)
- [Authentication](auth.md)

View file

@ -0,0 +1,151 @@
# Providers Overview
PicoClaw supports multiple LLM providers. This guide helps you choose and configure the right provider.
## Quick Comparison
| Provider | Free Tier | Best For | Auth Method |
|----------|-----------|----------|-------------|
| [OpenRouter](openrouter.md) | 200K tokens/mo | Multi-model access | API Key |
| [Zhipu](zhipu.md) | 200K tokens/mo | Chinese users | API Key |
| [Anthropic](anthropic.md) | Varies | Claude models | API Key, OAuth |
| [OpenAI](openai.md) | Varies | GPT models | API Key, OAuth |
| [Gemini](gemini.md) | Yes | Google models | API Key |
| [Groq](groq.md) | Yes | Fast inference | API Key |
| [DeepSeek](deepseek.md) | Yes | Reasoning | API Key |
| [Ollama](ollama.md) | Free | Local models | None |
| [vLLM](vllm.md) | Free | Self-hosted | API Key |
## Recommended Providers
### For Most Users: OpenRouter
OpenRouter provides access to many models (Claude, GPT, Llama, etc.) with a single API key.
```json
{
"agents": { "defaults": { "model": "anthropic/claude-opus-4-5" } },
"providers": {
"openrouter": {
"api_key": "sk-or-v1-xxx"
}
}
}
```
### For Chinese Users: Zhipu
Zhipu offers Chinese-optimized models with good free tier.
```json
{
"agents": { "defaults": { "model": "glm-4.7" } },
"providers": {
"zhipu": {
"api_key": "your-zhipu-key"
}
}
}
```
### For Local/Offline: Ollama
Run models locally without internet.
```json
{
"agents": { "defaults": { "model": "llama3.2" } },
"providers": {
"ollama": {
"api_base": "http://localhost:11434/v1"
}
}
}
```
## Provider Selection
PicoClaw selects providers in this order:
1. **Explicit provider** in config:
```json
"provider": "openrouter"
```
2. **Model prefix**:
```json
"model": "openrouter/anthropic/claude-opus-4-5"
```
3. **First API key found** (default behavior)
## Model Fallbacks
Configure automatic fallback if primary model fails:
```json
{
"agents": {
"defaults": {
"model": "claude-opus-4-5",
"model_fallbacks": ["gpt-4o", "glm-4.7"]
}
}
}
```
## Authentication Methods
### API Key (Recommended)
Simplest method - add your key to config:
```json
{
"providers": {
"openrouter": {
"api_key": "sk-or-v1-xxx"
}
}
}
```
### Environment Variable
Override config with environment variables:
```bash
export PICOCLAW_PROVIDERS_OPENROUTER_API_KEY="sk-or-v1-xxx"
```
### OAuth
For OpenAI and Anthropic, use OAuth login:
```bash
picoclaw auth login --provider openai
```
## Getting API Keys
| Provider | Get API Key |
|----------|-------------|
| OpenRouter | [openrouter.ai/keys](https://openrouter.ai/keys) |
| Zhipu | [bigmodel.cn](https://open.bigmodel.cn/usercenter/proj-mgmt/apikeys) |
| Anthropic | [console.anthropic.com](https://console.anthropic.com) |
| OpenAI | [platform.openai.com](https://platform.openai.com) |
| Gemini | [aistudio.google.com](https://aistudio.google.com) |
| Groq | [console.groq.com](https://console.groq.com) |
| DeepSeek | [platform.deepseek.com](https://platform.deepseek.com) |
## Provider-Specific Guides
- [OpenRouter](openrouter.md) - Multi-model access
- [Zhipu](zhipu.md) - Chinese AI models
- [Anthropic](anthropic.md) - Claude models
- [OpenAI](openai.md) - GPT models
- [Gemini](gemini.md) - Google Gemini
- [Groq](groq.md) - Fast inference + voice
- [DeepSeek](deepseek.md) - DeepSeek models
- [Ollama](ollama.md) - Local models
- [vLLM](vllm.md) - Self-hosted models

View file

@ -0,0 +1,237 @@
# Anthropic Provider
Use Anthropic's Claude models directly through their API.
## Why Anthropic?
- **Direct access**: No middleman, direct API access
- **Latest models**: Immediate access to newest Claude versions
- **Native features**: Full feature support
- **OAuth support**: Secure authentication
## Setup
### Step 1: Get API Key
1. Go to [console.anthropic.com](https://console.anthropic.com)
2. Sign in or create an account
3. Navigate to API Keys
4. Create a new API key
5. Copy the key (starts with `sk-ant-`)
### Step 2: Configure
Edit `~/.picoclaw/config.json`:
```json
{
"agents": {
"defaults": {
"model": "claude-opus-4-5"
}
},
"providers": {
"anthropic": {
"api_key": "sk-ant-YOUR-API-KEY",
"api_base": "https://api.anthropic.com"
}
}
}
```
## Configuration Options
| Option | Required | Default | Description |
|--------|----------|---------|-------------|
| `api_key` | Yes* | - | Your Anthropic API key |
| `api_base` | No | `https://api.anthropic.com` | API endpoint |
*Required unless using OAuth
## Available Models
| Model | Model Name | Best For |
|-------|------------|----------|
| Claude Opus 4.5 | `claude-opus-4-5` | Most capable, complex tasks |
| Claude Opus 4 | `claude-opus-4-20250514` | High-intelligence tasks |
| Claude Sonnet 4 | `claude-sonnet-4-20250514` | Fast + capable |
| Claude Sonnet 3.7 | `claude-3-7-sonnet-20250219` | Balanced performance |
| Claude Sonnet 3.5 | `claude-3-5-sonnet-20241022` | Fast, efficient |
## OAuth Authentication
For secure authentication without storing API keys:
```bash
# Login with OAuth
picoclaw auth login --provider anthropic
# Use device code flow (for headless environments)
picoclaw auth login --provider anthropic --device-code
```
After OAuth login, you don't need to store the API key in config.
## Model Format
Use the model name directly (no provider prefix needed):
```json
{
"agents": {
"defaults": {
"model": "claude-opus-4-5"
}
}
}
```
Or with provider prefix:
```json
{
"agents": {
"defaults": {
"model": "anthropic/claude-opus-4-5"
}
}
}
```
## Fallback Configuration
```json
{
"agents": {
"defaults": {
"model": "claude-opus-4-5",
"model_fallbacks": [
"claude-sonnet-4-20250514",
"claude-3-5-sonnet-20241022"
]
}
}
}
```
## Environment Variable
```bash
export PICOCLAW_PROVIDERS_ANTHROPIC_API_KEY="sk-ant-xxx"
```
## Pricing
Check [anthropic.com/pricing](https://www.anthropic.com/pricing) for current pricing.
Claude models are typically:
- Opus: Highest cost, best capability
- Sonnet: Mid-range cost, good balance
- Haiku: Lowest cost, fastest
## Rate Limits
Anthropic applies rate limits based on your tier:
| Tier | Requests per Minute | Tokens per Minute |
|------|---------------------|-------------------|
| Free | Varies | Varies |
| Tier 1 | 50 | 100,000 |
| Tier 2 | 100 | 200,000 |
| Higher | Custom | Custom |
Handle rate limits with fallbacks:
```json
{
"agents": {
"defaults": {
"model": "claude-opus-4-5",
"model_fallbacks": ["claude-sonnet-4-20250514"]
}
}
}
```
## Usage Examples
```bash
# Use default model
picoclaw agent -m "Hello!"
# Specify model
picoclaw agent -m "Hello!" # Uses config model
```
## Features
### Extended Thinking
Claude models support extended thinking for complex reasoning:
```json
{
"agents": {
"defaults": {
"model": "claude-opus-4-5",
"thinking": {
"enabled": true,
"budget_tokens": 10000
}
}
}
}
```
### Vision
Claude can analyze images (when supported by the channel):
```json
{
"agents": {
"defaults": {
"model": "claude-opus-4-5",
"vision": true
}
}
}
```
## Troubleshooting
### Invalid API Key
```
Error: invalid_api_key
```
Verify your API key:
1. Check key starts with `sk-ant-`
2. Ensure key is active in console
3. Check for typos
### Rate Limited
```
Error: rate_limit_exceeded
```
Solutions:
1. Wait and retry
2. Set up fallback models
3. Upgrade your tier
### Model Not Found
```
Error: model_not_found
```
Check model name is correct. Use exact model IDs from the Anthropic documentation.
## See Also
- [Providers Overview](README.md)
- [Configuration Reference](../../configuration/config-file.md)
- [Model Fallbacks](../advanced/model-fallbacks.md)

View file

@ -0,0 +1,234 @@
# DeepSeek Provider
Use DeepSeek's models for reasoning and general tasks.
## Why DeepSeek?
- **Strong reasoning**: Excellent at complex reasoning tasks
- **Cost-effective**: Competitive pricing
- **Long context**: Up to 64K context
- **Code generation**: Strong coding capabilities
## Setup
### Step 1: Get API Key
1. Go to [platform.deepseek.com](https://platform.deepseek.com)
2. Sign in or create an account
3. Navigate to API Keys
4. Create a new API key
5. Copy the key (starts with `sk-`)
### Step 2: Configure
Edit `~/.picoclaw/config.json`:
```json
{
"agents": {
"defaults": {
"model": "deepseek-chat"
}
},
"providers": {
"deepseek": {
"api_key": "sk-YOUR-API-KEY",
"api_base": "https://api.deepseek.com"
}
}
}
```
## Configuration Options
| Option | Required | Default | Description |
|--------|----------|---------|-------------|
| `api_key` | Yes | - | Your DeepSeek API key |
| `api_base` | No | `https://api.deepseek.com` | API endpoint |
## Available Models
| Model | Model Name | Best For |
|-------|------------|----------|
| DeepSeek Chat | `deepseek-chat` | General conversation |
| DeepSeek Reasoner | `deepseek-reasoner` | Complex reasoning |
### Model Comparison
| Feature | deepseek-chat | deepseek-reasoner |
|---------|---------------|-------------------|
| Context | 64K | 64K |
| Best for | General tasks | Complex reasoning |
| Speed | Fast | Slower (thinks more) |
## Model Format
Use the model name directly:
```json
{
"agents": {
"defaults": {
"model": "deepseek-chat"
}
}
}
```
Or with provider prefix:
```json
{
"agents": {
"defaults": {
"model": "deepseek/deepseek-chat"
}
}
}
```
## Fallback Configuration
```json
{
"agents": {
"defaults": {
"model": "deepseek-reasoner",
"model_fallbacks": [
"deepseek-chat"
]
}
}
}
```
## Environment Variable
```bash
export PICOCLAW_PROVIDERS_DEEPSEEK_API_KEY="sk-xxx"
```
## Pricing
Check [platform.deepseek.com/pricing](https://platform.deepseek.com/pricing) for current pricing.
Approximate costs (per 1M tokens):
| Model | Input | Output |
|-------|-------|--------|
| deepseek-chat | $0.14 | $0.28 |
| deepseek-reasoner | $0.55 | $2.19 |
## Usage Examples
```bash
# General chat
picoclaw agent -m "Hello!"
# Complex reasoning (with reasoner model)
picoclaw agent -m "Solve this step by step: What is 15% of 847?"
```
## DeepSeek Reasoner
The `deepseek-reasoner` model is optimized for complex reasoning:
- Shows thinking process
- Better at math and logic
- Good for analysis tasks
### When to Use Reasoner
- Mathematical problems
- Logical reasoning
- Multi-step analysis
- Complex decision making
### Example
```
User: If I have 5 apples and give away 2, then buy 3 more, how many do I have?
Agent (using reasoner):
Let me work through this step by step:
1. Start with 5 apples
2. Give away 2: 5 - 2 = 3 apples
3. Buy 3 more: 3 + 3 = 6 apples
You have 6 apples.
```
## Troubleshooting
### Invalid API Key
```
Error: Authentication Error
```
Verify your API key:
1. Check key is correctly copied
2. Ensure key is active in platform
3. Check for typos
### Rate Limited
```
Error: Rate limit exceeded
```
Solutions:
1. Wait and retry
2. Set up fallback models
3. Check your usage limits
### Insufficient Balance
```
Error: Insufficient balance
```
Add funds to your DeepSeek account at [platform.deepseek.com](https://platform.deepseek.com).
### Context Length Exceeded
```
Error: context_length_exceeded
```
Solutions:
1. Reduce message length
2. Clear session history
3. Start a new session
## Best Practices
1. **Use chat for general tasks** - Faster and more efficient
2. **Use reasoner for complex problems** - Better reasoning capability
3. **Set up fallbacks** - For reliability
4. **Monitor usage** - Track token consumption
## Using via OpenRouter
Alternatively, access DeepSeek through OpenRouter:
```json
{
"providers": {
"openrouter": {
"api_key": "sk-or-v1-xxx"
}
},
"agents": {
"defaults": {
"model": "deepseek/deepseek-chat"
}
}
}
```
## See Also
- [Providers Overview](README.md)
- [Configuration Reference](../../configuration/config-file.md)
- [Model Fallbacks](../advanced/model-fallbacks.md)

View file

@ -0,0 +1,260 @@
# Gemini Provider
Use Google's Gemini models through the Gemini API.
## Why Gemini?
- **Free tier**: Generous free tier for development
- **Large context**: Up to 1M tokens context window
- **Multimodal**: Native support for text, images, audio, video
- **Fast**: Quick response times
## Setup
### Step 1: Get API Key
1. Go to [aistudio.google.com](https://aistudio.google.com)
2. Sign in with your Google account
3. Click "Get API Key"
4. Create a new API key
5. Copy the key
### Step 2: Configure
Edit `~/.picoclaw/config.json`:
```json
{
"agents": {
"defaults": {
"model": "gemini-2.0-flash"
}
},
"providers": {
"gemini": {
"api_key": "YOUR-API-KEY",
"api_base": "https://generativelanguage.googleapis.com/v1beta"
}
}
}
```
## Configuration Options
| Option | Required | Default | Description |
|--------|----------|---------|-------------|
| `api_key` | Yes | - | Your Gemini API key |
| `api_base` | No | `https://generativelanguage.googleapis.com/v1beta` | API endpoint |
## Available Models
| Model | Model Name | Best For |
|-------|------------|----------|
| Gemini 2.0 Flash | `gemini-2.0-flash` | Fast, efficient |
| Gemini 2.0 Pro | `gemini-2.0-pro-exp` | Experimental, advanced |
| Gemini 1.5 Pro | `gemini-1.5-pro` | Large context, complex tasks |
| Gemini 1.5 Flash | `gemini-1.5-flash` | Fast, cost-effective |
| Gemini 1.5 Flash-8B | `gemini-1.5-flash-8b` | Smallest, fastest |
## Model Capabilities
| Model | Context | Multimodal | Best Use |
|-------|---------|------------|----------|
| Gemini 2.0 Flash | 1M tokens | Yes | General use |
| Gemini 1.5 Pro | 2M tokens | Yes | Long documents |
| Gemini 1.5 Flash | 1M tokens | Yes | Fast responses |
## Model Format
Use the model name directly:
```json
{
"agents": {
"defaults": {
"model": "gemini-2.0-flash"
}
}
}
```
Or with provider prefix:
```json
{
"agents": {
"defaults": {
"model": "gemini/gemini-2.0-flash"
}
}
}
```
## Fallback Configuration
```json
{
"agents": {
"defaults": {
"model": "gemini-2.0-flash",
"model_fallbacks": [
"gemini-1.5-flash",
"gemini-1.5-flash-8b"
]
}
}
}
```
## Environment Variable
```bash
export PICOCLAW_PROVIDERS_GEMINI_API_KEY="your-api-key"
```
## Pricing
Check [ai.google.dev/pricing](https://ai.google.dev/pricing) for current pricing.
### Free Tier
| Model | Requests per Day | Tokens per Minute |
|-------|------------------|-------------------|
| Gemini 2.0 Flash | 1,500 | 1M |
| Gemini 1.5 Flash | 1,500 | 1M |
| Gemini 1.5 Pro | 50 | 32K |
### Paid Tier
Higher limits available with billing enabled.
## Usage Examples
```bash
# Use default model
picoclaw agent -m "Hello!"
# Gemini handles long contexts well
picoclaw agent -m "Summarize this 100-page document..."
```
## Special Features
### Large Context Window
Gemini supports up to 2M token context, ideal for:
- Long document analysis
- Multi-document summarization
- Extended conversation history
- Large codebase analysis
### Multimodal Input
Gemini can process:
- Text
- Images
- Audio
- Video
Configure for vision:
```json
{
"agents": {
"defaults": {
"model": "gemini-2.0-flash",
"vision": true
}
}
}
```
### Safety Settings
Configure content filtering:
```json
{
"providers": {
"gemini": {
"api_key": "your-key",
"safety_settings": {
"harassment": "BLOCK_MEDIUM_AND_ABOVE",
"hate_speech": "BLOCK_MEDIUM_AND_ABOVE",
"sexually_explicit": "BLOCK_MEDIUM_AND_ABOVE",
"dangerous_content": "BLOCK_MEDIUM_AND_ABOVE"
}
}
}
}
```
## Troubleshooting
### Invalid API Key
```
Error: API key not valid
```
Verify your API key:
1. Check key is correctly copied
2. Ensure key is active in AI Studio
3. Try regenerating the key
### Resource Exhausted
```
Error: RESOURCE_EXHAUSTED
```
Solutions:
1. Wait and retry (rate limit)
2. Check daily quota
3. Enable billing for higher limits
### Content Filtered
```
Error: content was blocked
```
Solutions:
1. Adjust safety settings
2. Rephrase your prompt
3. Use a different model
### Context Too Long
Even with large context, you may hit limits:
1. Reduce context size
2. Use document summarization
3. Split into multiple requests
## Using via OpenRouter
Alternatively, access Gemini through OpenRouter:
```json
{
"providers": {
"openrouter": {
"api_key": "sk-or-v1-xxx"
}
},
"agents": {
"defaults": {
"model": "google/gemini-2.0-flash-001"
}
}
}
```
## See Also
- [Providers Overview](README.md)
- [Configuration Reference](../../configuration/config-file.md)
- [Model Fallbacks](../advanced/model-fallbacks.md)

View file

@ -0,0 +1,270 @@
# Groq Provider
Use Groq's ultra-fast inference for LLMs and voice transcription.
## Why Groq?
- **Extremely fast**: Sub-second response times
- **Free tier**: Generous free tier available
- **Voice transcription**: Whisper-large-v3 for audio
- **Open models**: Llama, Mixtral, and more
## Setup
### Step 1: Get API Key
1. Go to [console.groq.com](https://console.groq.com)
2. Sign in or create an account
3. Navigate to API Keys
4. Create a new API key
5. Copy the key (starts with `gsk_`)
### Step 2: Configure
Edit `~/.picoclaw/config.json`:
```json
{
"agents": {
"defaults": {
"model": "llama-3.3-70b-versatile"
}
},
"providers": {
"groq": {
"api_key": "gsk_YOUR-API-KEY",
"api_base": "https://api.groq.com/openai/v1"
}
}
}
```
## Configuration Options
| Option | Required | Default | Description |
|--------|----------|---------|-------------|
| `api_key` | Yes | - | Your Groq API key |
| `api_base` | No | `https://api.groq.com/openai/v1` | API endpoint |
## Available Models
### Chat Models
| Model | Model Name | Best For |
|-------|------------|----------|
| Llama 3.3 70B | `llama-3.3-70b-versatile` | General use, balanced |
| Llama 3.3 70B Specdec | `llama-3.3-70b-specdec` | Speculative decoding, faster |
| Llama 3.1 8B | `llama-3.1-8b-instant` | Fast, simple tasks |
| Mixtral 8x7B | `mixtral-8x7b-32768` | Multilingual, 32K context |
| Gemma 2 9B | `gemma2-9b-it` | Lightweight, efficient |
### Audio Models
| Model | Model Name | Use |
|-------|------------|-----|
| Whisper Large v3 | `whisper-large-v3` | Audio transcription |
| Whisper Large v3 Turbo | `whisper-large-v3-turbo` | Faster transcription |
## Model Format
Use the model name directly:
```json
{
"agents": {
"defaults": {
"model": "llama-3.3-70b-versatile"
}
}
}
```
Or with provider prefix:
```json
{
"agents": {
"defaults": {
"model": "groq/llama-3.3-70b-versatile"
}
}
}
```
## Fallback Configuration
```json
{
"agents": {
"defaults": {
"model": "llama-3.3-70b-versatile",
"model_fallbacks": [
"llama-3.1-8b-instant",
"mixtral-8x7b-32768"
]
}
}
}
```
## Environment Variable
```bash
export PICOCLAW_PROVIDERS_GROQ_API_KEY="gsk_xxx"
```
## Pricing
Groq offers a generous free tier.
### Free Tier
| Resource | Limit |
|----------|-------|
| Requests per minute | 30 |
| Tokens per minute | 18,000 |
| Requests per day | 14,400 |
### Paid Tier
Higher limits available with paid plans. Check [groq.com/pricing](https://groq.com/pricing) for details.
## Voice Transcription
Groq provides ultra-fast Whisper transcription.
### Enable Voice Transcription
```json
{
"providers": {
"groq": {
"api_key": "gsk_xxx"
}
},
"agents": {
"defaults": {
"voice_transcription": {
"enabled": true,
"provider": "groq",
"model": "whisper-large-v3"
}
}
}
}
```
### Supported Formats
- MP3
- MP4
- MPEG
- MPGA
- M4A
- WAV
- WebM
### Use with Telegram
Voice messages in Telegram will be automatically transcribed:
```json
{
"channels": {
"telegram": {
"enabled": true,
"token": "your-bot-token"
}
},
"agents": {
"defaults": {
"voice_transcription": {
"enabled": true,
"provider": "groq"
}
}
}
}
```
## Usage Examples
```bash
# Use default model
picoclaw agent -m "Hello!"
# Groq is extremely fast
picoclaw agent -m "Write a quick summary of..."
```
## Performance
Groq uses custom LPU (Language Processing Unit) hardware:
| Model | Typical Latency |
|-------|-----------------|
| Llama 3.3 70B | < 500ms |
| Llama 3.1 8B | < 200ms |
| Whisper Large | Real-time |
## Troubleshooting
### Invalid API Key
```
Error: invalid_api_key
```
Verify your API key:
1. Check key starts with `gsk_`
2. Ensure key is active
3. Check for typos
### Rate Limited
```
Error: rate_limit_exceeded
```
Solutions:
1. Wait and retry
2. Set up fallback models
3. Upgrade to paid tier
### Model Not Available
```
Error: model_not_found
```
Check available models at [console.groq.com/models](https://console.groq.com/models)
### Audio File Too Large
```
Error: file_too_large
```
Audio file limits:
- Maximum file size: 25MB
- Maximum duration: ~30 minutes
## Best Practices
### For Chat
1. Use `llama-3.3-70b-versatile` for best quality
2. Use `llama-3.1-8b-instant` for simple, fast tasks
3. Set up fallbacks for reliability
### For Voice
1. Use `whisper-large-v3-turbo` for faster transcription
2. Use `whisper-large-v3` for better accuracy
3. Ensure audio is clear for best results
## See Also
- [Providers Overview](README.md)
- [Configuration Reference](../../configuration/config-file.md)
- [Voice Transcription](../advanced/voice-transcription.md)

View file

@ -0,0 +1,341 @@
# Ollama Provider
Run LLMs locally using Ollama for offline, private, and cost-free inference.
## Why Ollama?
- **Free**: No API costs
- **Private**: Data stays on your machine
- **Offline**: Works without internet
- **Flexible**: Run many open-source models
## Prerequisites
- Sufficient RAM (8GB+ recommended for larger models)
- Sufficient disk space (models are 2-10GB+)
- Linux, macOS, or Windows (with WSL2)
## Setup
### Step 1: Install Ollama
**Linux/macOS:**
```bash
curl -fsSL https://ollama.com/install.sh | sh
```
**Or download from [ollama.com](https://ollama.com)**
### Step 2: Pull a Model
```bash
# Pull a model (example: Llama 3.2)
ollama pull llama3.2
# List available models
ollama list
```
### Step 3: Configure PicoClaw
Edit `~/.picoclaw/config.json`:
```json
{
"agents": {
"defaults": {
"model": "llama3.2"
}
},
"providers": {
"ollama": {
"api_base": "http://localhost:11434/v1"
}
}
}
```
## Configuration Options
| Option | Required | Default | Description |
|--------|----------|---------|-------------|
| `api_base` | No | `http://localhost:11434/v1` | Ollama API endpoint |
No API key needed - Ollama runs locally.
## Popular Models
| Model | Command | Size | Best For |
|-------|---------|------|----------|
| Llama 3.2 3B | `ollama pull llama3.2` | 2GB | General use |
| Llama 3.2 1B | `ollama pull llama3.2:1b` | 1GB | Fast, lightweight |
| Llama 3.1 8B | `ollama pull llama3.1` | 5GB | Better quality |
| Llama 3.1 70B | `ollama pull llama3.1:70b` | 40GB | Best quality |
| Mistral | `ollama pull mistral` | 4GB | Efficient |
| CodeLlama | `ollama pull codellama` | 4GB | Code generation |
| Phi-3 | `ollama pull phi3` | 2GB | Microsoft's small model |
| Gemma 2 | `ollama pull gemma2` | 5GB | Google's open model |
| Qwen 2.5 | `ollama pull qwen2.5` | 5GB | Multilingual |
## Model Management
### Pull Models
```bash
# Pull latest version
ollama pull llama3.2
# Pull specific version
ollama pull llama3.2:3b
```
### List Models
```bash
ollama list
```
Output:
```
NAME ID SIZE MODIFIED
llama3.2:latest 123abc... 2.0 GB 2 hours ago
mistral:latest 456def... 4.1 GB 3 days ago
```
### Remove Models
```bash
ollama rm old-model
```
### Update Models
```bash
ollama pull llama3.2
```
## Model Format
Use the model name as shown in `ollama list`:
```json
{
"agents": {
"defaults": {
"model": "llama3.2"
}
}
}
```
Or with provider prefix:
```json
{
"agents": {
"defaults": {
"model": "ollama/llama3.2"
}
}
}
```
## Fallback Configuration
Combine local and cloud models:
```json
{
"agents": {
"defaults": {
"model": "llama3.2",
"model_fallbacks": [
"openrouter/anthropic/claude-sonnet-4"
]
}
},
"providers": {
"ollama": {
"api_base": "http://localhost:11434/v1"
},
"openrouter": {
"api_key": "sk-or-v1-xxx"
}
}
}
```
## Remote Ollama
Connect to Ollama running on another machine:
```json
{
"providers": {
"ollama": {
"api_base": "http://192.168.1.100:11434/v1"
}
}
}
```
### Start Ollama with Network Access
```bash
# Set host to listen on all interfaces
OLLAMA_HOST=0.0.0.0 ollama serve
```
## Resource Requirements
### RAM Guidelines
| Model Size | Minimum RAM | Recommended RAM |
|------------|-------------|-----------------|
| 1B parameters | 4GB | 8GB |
| 3B parameters | 6GB | 12GB |
| 7-8B parameters | 8GB | 16GB |
| 13B parameters | 16GB | 32GB |
| 70B parameters | 48GB | 64GB+ |
### GPU Acceleration
Ollama automatically uses GPU when available:
- **NVIDIA**: CUDA support (requires nvidia drivers)
- **AMD**: ROCm support
- **Apple Silicon**: Metal support (M1/M2/M3)
Check GPU usage:
```bash
# NVIDIA
nvidia-smi
# Or during inference
ollama run llama3.2
```
## Custom Models
### Create a Modelfile
```dockerfile
FROM llama3.2
# Set parameters
PARAMETER temperature 0.7
PARAMETER num_ctx 4096
# Set system prompt
SYSTEM You are a helpful coding assistant.
```
### Build Custom Model
```bash
ollama create my-coder -f Modelfile
```
### Use Custom Model
```json
{
"agents": {
"defaults": {
"model": "my-coder"
}
}
}
```
## Troubleshooting
### Ollama Not Running
```
Error: connection refused
```
Start Ollama:
```bash
ollama serve
```
Or run interactively:
```bash
ollama run llama3.2
```
### Model Not Found
```
Error: model 'xxx' not found
```
Pull the model first:
```bash
ollama pull xxx
```
### Out of Memory
```
Error: out of memory
```
Solutions:
1. Use a smaller model
2. Close other applications
3. Reduce context length
### Slow Responses
Solutions:
1. Use a smaller model
2. Ensure GPU acceleration
3. Check system resources
### Port Already in Use
```
Error: address already in use
```
Change Ollama port:
```bash
OLLAMA_HOST=0.0.0.0:11435 ollama serve
```
Update PicoClaw config:
```json
{
"providers": {
"ollama": {
"api_base": "http://localhost:11435/v1"
}
}
}
```
## Best Practices
1. **Start with small models** - Test with 1B-3B models first
2. **Monitor resources** - Watch RAM and GPU usage
3. **Use quantized models** - Default models are already optimized
4. **Combine with cloud** - Use fallbacks for reliability
5. **Keep models updated** - `ollama pull` to update
## See Also
- [Providers Overview](README.md)
- [Configuration Reference](../../configuration/config-file.md)
- [Model Fallbacks](../advanced/model-fallbacks.md)
- [Ollama Documentation](https://github.com/ollama/ollama)

View file

@ -0,0 +1,268 @@
# OpenAI Provider
Use OpenAI's GPT models directly through their API.
## Why OpenAI?
- **GPT models**: Access to GPT-4, GPT-4o, and GPT-3.5
- **DALL-E**: Image generation capabilities
- **Whisper**: Audio transcription
- **Native features**: Full OpenAI API support
## Setup
### Step 1: Get API Key
1. Go to [platform.openai.com](https://platform.openai.com)
2. Sign in or create an account
3. Navigate to API Keys
4. Create a new secret key
5. Copy the key (starts with `sk-`)
### Step 2: Configure
Edit `~/.picoclaw/config.json`:
```json
{
"agents": {
"defaults": {
"model": "gpt-4o"
}
},
"providers": {
"openai": {
"api_key": "sk-YOUR-API-KEY",
"api_base": "https://api.openai.com/v1"
}
}
}
```
## Configuration Options
| Option | Required | Default | Description |
|--------|----------|---------|-------------|
| `api_key` | Yes* | - | Your OpenAI API key |
| `api_base` | No | `https://api.openai.com/v1` | API endpoint |
| `organization` | No | - | Organization ID |
*Required unless using OAuth
## Available Models
### Chat Models
| Model | Model Name | Best For |
|-------|------------|----------|
| GPT-4o | `gpt-4o` | Latest flagship, multimodal |
| GPT-4o Mini | `gpt-4o-mini` | Fast, cost-effective |
| GPT-4 Turbo | `gpt-4-turbo` | Previous generation flagship |
| GPT-4 | `gpt-4` | Standard GPT-4 |
| GPT-3.5 Turbo | `gpt-3.5-turbo` | Fast, affordable |
### Reasoning Models
| Model | Model Name | Best For |
|-------|------------|----------|
| o1 | `o1` | Complex reasoning |
| o1-mini | `o1-mini` | Fast reasoning tasks |
| o1-preview | `o1-preview` | Preview reasoning model |
## OAuth Authentication
For secure authentication without storing API keys:
```bash
# Login with OAuth
picoclaw auth login --provider openai
# Use device code flow (for headless environments)
picoclaw auth login --provider openai --device-code
```
## Model Format
Use the model name directly:
```json
{
"agents": {
"defaults": {
"model": "gpt-4o"
}
}
}
```
Or with provider prefix:
```json
{
"agents": {
"defaults": {
"model": "openai/gpt-4o"
}
}
}
```
## Fallback Configuration
```json
{
"agents": {
"defaults": {
"model": "gpt-4o",
"model_fallbacks": [
"gpt-4o-mini",
"gpt-3.5-turbo"
]
}
}
}
```
## Environment Variable
```bash
export PICOCLAW_PROVIDERS_OPENAI_API_KEY="sk-xxx"
```
## Pricing
Check [openai.com/pricing](https://openai.com/pricing) for current pricing.
Approximate costs (per 1M tokens):
| Model | Input | Output |
|-------|-------|--------|
| GPT-4o | $2.50 | $10.00 |
| GPT-4o Mini | $0.15 | $0.60 |
| GPT-4 Turbo | $10.00 | $30.00 |
| GPT-3.5 Turbo | $0.50 | $1.50 |
## Rate Limits
OpenAI applies rate limits:
| Tier | Requests per Minute | Tokens per Minute |
|------|---------------------|-------------------|
| Free | 3 | 40,000 |
| Tier 1 | 500 | 200,000 |
| Tier 2 | 5,000 | 2,000,000 |
## Usage Examples
```bash
# Use default model
picoclaw agent -m "Hello!"
# With specific model in config
picoclaw agent -m "Explain quantum computing"
```
## Special Features
### Function Calling
OpenAI models support function calling, which PicoClaw uses for tools.
### Vision
GPT-4o and GPT-4 Turbo support image analysis:
```json
{
"agents": {
"defaults": {
"model": "gpt-4o",
"vision": true
}
}
}
```
### Structured Outputs
For applications requiring structured responses:
```json
{
"agents": {
"defaults": {
"model": "gpt-4o",
"response_format": "json_object"
}
}
}
```
## Using with Azure OpenAI
For Azure OpenAI Service:
```json
{
"providers": {
"openai": {
"api_key": "your-azure-key",
"api_base": "https://your-resource.openai.azure.com/openai/deployments/your-deployment",
"api_version": "2024-02-15-preview",
"azure": true
}
}
}
```
## Troubleshooting
### Invalid API Key
```
Error: incorrect_api_key
```
Verify your API key:
1. Check key starts with `sk-`
2. Ensure key is active
3. Check for typos
### Insufficient Quota
```
Error: insufficient_quota
```
Solutions:
1. Add billing information
2. Wait for quota reset
3. Use fallback models
### Rate Limited
```
Error: rate_limit_exceeded
```
Solutions:
1. Wait and retry
2. Set up fallback models
3. Upgrade your tier
### Context Length Exceeded
```
Error: context_length_exceeded
```
Solutions:
1. Reduce message length
2. Clear session history
3. Use a model with larger context
## See Also
- [Providers Overview](README.md)
- [Configuration Reference](../../configuration/config-file.md)
- [Model Fallbacks](../advanced/model-fallbacks.md)

View file

@ -0,0 +1,114 @@
# OpenRouter Provider
OpenRouter is the recommended provider for most users. It provides access to many LLM models through a single API.
## Why OpenRouter?
- **Multi-model access**: Claude, GPT, Llama, Mistral, and more
- **Free tier**: 200K tokens per month
- **Simple pricing**: Pay per use after free tier
- **Single API key**: Access all models with one key
## Setup
### Step 1: Get API Key
1. Go to [openrouter.ai/keys](https://openrouter.ai/keys)
2. Sign in or create an account
3. Create an API key
4. Copy the key (starts with `sk-or-v1-`)
### Step 2: Configure
Edit `~/.picoclaw/config.json`:
```json
{
"agents": {
"defaults": {
"model": "anthropic/claude-opus-4-5"
}
},
"providers": {
"openrouter": {
"api_key": "sk-or-v1-YOUR-API-KEY",
"api_base": "https://openrouter.ai/api/v1"
}
}
}
```
## Configuration Options
| Option | Required | Default | Description |
|--------|----------|---------|-------------|
| `api_key` | Yes | - | Your OpenRouter API key |
| `api_base` | No | `https://openrouter.ai/api/v1` | API endpoint |
## Popular Models
| Model | Model Name | Notes |
|-------|------------|-------|
| Claude Opus 4.5 | `anthropic/claude-opus-4-5` | Most capable |
| Claude Sonnet 4 | `anthropic/claude-sonnet-4` | Fast + capable |
| GPT-4o | `openai/gpt-4o` | OpenAI flagship |
| GPT-4o Mini | `openai/gpt-4o-mini` | Fast, cheaper |
| Llama 3.3 70B | `meta-llama/llama-3.3-70b-instruct` | Open model |
| Gemini 2.0 Flash | `google/gemini-2.0-flash-001` | Fast Google model |
## Model Format
Use the format `provider/model-name`:
```json
{
"agents": {
"defaults": {
"model": "anthropic/claude-opus-4-5"
}
}
}
```
## Fallback Configuration
Set up fallbacks for reliability:
```json
{
"agents": {
"defaults": {
"model": "anthropic/claude-opus-4-5",
"model_fallbacks": [
"anthropic/claude-sonnet-4",
"openai/gpt-4o"
]
}
}
}
```
## Usage Examples
```bash
# Use default model
picoclaw agent -m "Hello!"
# With specific model
picoclaw agent -m "Hello!" # Uses config model
```
## Pricing
Check [openrouter.ai/models](https://openrouter.ai/models) for current pricing.
## Environment Variable
```bash
export PICOCLAW_PROVIDERS_OPENROUTER_API_KEY="sk-or-v1-xxx"
```
## See Also
- [Providers Overview](README.md)
- [Configuration Reference](../../configuration/config-file.md)

View file

@ -0,0 +1,363 @@
# vLLM Provider
Use vLLM for high-performance, self-hosted LLM serving.
## Why vLLM?
- **High throughput**: Optimized for production workloads
- **Memory efficient**: PagedAttention for better GPU utilization
- **OpenAI compatible**: Drop-in replacement for OpenAI API
- **Flexible**: Supports many open-source models
## Prerequisites
- NVIDIA GPU (CUDA support)
- Docker (recommended) or Python environment
- Sufficient GPU memory for your model
## Setup
### Option 1: Docker (Recommended)
```bash
# Pull vLLM image
docker pull vllm/vllm-openai:latest
# Run vLLM server
docker run --gpus all \
-v ~/.cache/huggingface:/root/.cache/huggingface \
-p 8000:8000 \
--ipc=host \
vllm/vllm-openai:latest \
--model meta-llama/Llama-3.2-3B-Instruct
```
### Option 2: Python Installation
```bash
# Install vLLM
pip install vllm
# Start server
python -m vllm.entrypoints.openai.api_server \
--model meta-llama/Llama-3.2-3B-Instruct \
--host 0.0.0.0 \
--port 8000
```
### Configure PicoClaw
Edit `~/.picoclaw/config.json`:
```json
{
"agents": {
"defaults": {
"model": "meta-llama/Llama-3.2-3B-Instruct"
}
},
"providers": {
"vllm": {
"api_base": "http://localhost:8000/v1"
}
}
}
```
## Configuration Options
| Option | Required | Default | Description |
|--------|----------|---------|-------------|
| `api_base` | No | `http://localhost:8000/v1` | vLLM API endpoint |
| `api_key` | No | - | API key (if configured) |
## Supported Models
vLLM supports many Hugging Face models:
| Model Family | Example Models |
|--------------|----------------|
| Llama | `meta-llama/Llama-3.2-3B-Instruct` |
| Mistral | `mistralai/Mistral-7B-Instruct-v0.3` |
| Qwen | `Qwen/Qwen2.5-7B-Instruct` |
| Phi | `microsoft/Phi-3-mini-4k-instruct` |
| Gemma | `google/gemma-2-9b-it` |
| Mixtral | `mistralai/Mixtral-8x7B-Instruct-v0.1` |
## vLLM Server Options
### GPU Selection
```bash
# Use specific GPUs
docker run --gpus '"device=0,1"' \
vllm/vllm-openai:latest \
--model meta-llama/Llama-3.2-3B-Instruct
```
### Memory Management
```bash
# GPU memory utilization (0-1)
--gpu-memory-utilization 0.9
# Max model length
--max-model-len 4096
```
### Performance Tuning
```bash
# Tensor parallelism (multi-GPU)
--tensor-parallel-size 2
# Batch size
--max-num-seqs 256
```
### Full Example
```bash
docker run --gpus all \
-v ~/.cache/huggingface:/root/.cache/huggingface \
-p 8000:8000 \
--ipc=host \
vllm/vllm-openai:latest \
--model meta-llama/Llama-3.2-3B-Instruct \
--gpu-memory-utilization 0.9 \
--max-model-len 4096 \
--max-num-seqs 128
```
## Model Format
Use the full Hugging Face model name:
```json
{
"agents": {
"defaults": {
"model": "meta-llama/Llama-3.2-3B-Instruct"
}
}
}
```
Or with provider prefix:
```json
{
"agents": {
"defaults": {
"model": "vllm/meta-llama/Llama-3.2-3B-Instruct"
}
}
}
```
## Using with Hugging Face Token
Some models require authentication:
```bash
# Login to Hugging Face
huggingface-cli login
# Or set token
export HF_TOKEN=your_token
# Docker with token
docker run --gpus all \
-e HF_TOKEN=your_token \
-v ~/.cache/huggingface:/root/.cache/huggingface \
-p 8000:8000 \
vllm/vllm-openai:latest \
--model meta-llama/Llama-3.2-3B-Instruct
```
## Fallback Configuration
Combine vLLM with cloud providers:
```json
{
"agents": {
"defaults": {
"model": "meta-llama/Llama-3.2-3B-Instruct",
"model_fallbacks": [
"openrouter/meta-llama/llama-3.2-3b-instruct"
]
}
},
"providers": {
"vllm": {
"api_base": "http://localhost:8000/v1"
},
"openrouter": {
"api_key": "sk-or-v1-xxx"
}
}
}
```
## GPU Requirements
### Approximate VRAM Requirements
| Model Size | Minimum VRAM | Recommended VRAM |
|------------|--------------|------------------|
| 3B | 8GB | 12GB |
| 7B | 16GB | 24GB |
| 13B | 24GB | 40GB |
| 70B | 80GB (2x40GB) | 160GB (4x40GB) |
### Multi-GPU Setup
```bash
# 2 GPUs with tensor parallelism
docker run --gpus all \
vllm/vllm-openai:latest \
--model meta-llama/Llama-3.1-70B-Instruct \
--tensor-parallel-size 2
```
## Remote vLLM
Connect to vLLM running on another server:
```json
{
"providers": {
"vllm": {
"api_base": "http://192.168.1.100:8000/v1"
}
}
}
```
## Authentication
Add API key authentication:
```bash
# Start vLLM with API key
--api-key your-secret-key
```
Configure PicoClaw:
```json
{
"providers": {
"vllm": {
"api_base": "http://localhost:8000/v1",
"api_key": "your-secret-key"
}
}
}
```
## Troubleshooting
### Server Not Running
```
Error: connection refused
```
Check vLLM server:
```bash
curl http://localhost:8000/v1/models
```
### Out of GPU Memory
```
Error: CUDA out of memory
```
Solutions:
1. Use smaller model
2. Reduce `--gpu-memory-utilization`
3. Reduce `--max-model-len`
4. Use multiple GPUs
### Model Not Found
```
Error: model not found
```
Ensure model name is correct and accessible:
```bash
# List available models
curl http://localhost:8000/v1/models
```
### Slow Responses
Solutions:
1. Check GPU utilization
2. Adjust batch size
3. Enable tensor parallelism
4. Check network latency
### Permission Denied (Hugging Face)
```
Error: Access to model is restricted
```
Login to Hugging Face:
```bash
huggingface-cli login
```
## Production Deployment
### Systemd Service
```ini
[Unit]
Description=vLLM Server
After=network.target
[Service]
Type=simple
User=vllm
ExecStart=/usr/bin/docker run --gpus all \
-v /var/lib/vllm:/root/.cache/huggingface \
-p 8000:8000 \
vllm/vllm-openai:latest \
--model meta-llama/Llama-3.2-3B-Instruct
Restart=always
[Install]
WantedBy=multi-user.target
```
### Kubernetes
See vLLM documentation for Kubernetes deployment with:
- GPU resource requests
- Horizontal scaling
- Load balancing
## Best Practices
1. **Use Docker** - Easier deployment and isolation
2. **Monitor GPU usage** - Watch VRAM and utilization
3. **Tune parameters** - Optimize for your workload
4. **Set up fallbacks** - Cloud providers for reliability
5. **Cache models** - Mount HuggingFace cache volume
## See Also
- [Providers Overview](README.md)
- [Configuration Reference](../../configuration/config-file.md)
- [Model Fallbacks](../advanced/model-fallbacks.md)
- [vLLM Documentation](https://docs.vllm.ai)

View file

@ -0,0 +1,119 @@
# Zhipu Provider
Zhipu (智谱) provides Chinese-optimized AI models through their GLM series.
## Why Zhipu?
- **Chinese language**: Optimized for Chinese users
- **Free tier**: 200K tokens per month
- **Multiple models**: GLM-4.7, GLM-4-Plus, and more
- **Direct access**: No intermediary
## Setup
### Step 1: Get API Key
1. Go to [bigmodel.cn](https://open.bigmodel.cn/usercenter/proj-mgmt/apikeys)
2. Register or sign in
3. Create an API key
4. Copy the key
### Step 2: Configure
Edit `~/.picoclaw/config.json`:
```json
{
"agents": {
"defaults": {
"model": "glm-4.7"
}
},
"providers": {
"zhipu": {
"api_key": "YOUR_ZHIPU_API_KEY",
"api_base": "https://open.bigmodel.cn/api/paas/v4"
}
}
}
```
## Configuration Options
| Option | Required | Default | Description |
|--------|----------|---------|-------------|
| `api_key` | Yes | - | Your Zhipu API key |
| `api_base` | No | `https://open.bigmodel.cn/api/paas/v4` | API endpoint |
## Available Models
| Model | Description |
|-------|-------------|
| `glm-4.7` | Latest GLM model (default) |
| `glm-4-plus` | Enhanced capabilities |
| `glm-4` | Standard GLM-4 |
| `glm-4-air` | Faster, lighter model |
| `glm-4-flash` | Fastest model |
## Model Format
Use just the model name (no provider prefix needed):
```json
{
"agents": {
"defaults": {
"model": "glm-4.7"
}
}
}
```
## Features
### Chinese Language Support
Zhipu models are optimized for:
- Chinese conversations
- Chinese document processing
- Chinese cultural context
### Multi-modal
Some Zhipu models support:
- Text generation
- Image understanding
- Code generation
## Content Filtering
Zhipu has content filtering. If you encounter filtering errors:
1. Rephrase your query
2. Avoid sensitive topics
3. Use a different model
## Environment Variable
```bash
export PICOCLAW_PROVIDERS_ZHIPU_API_KEY="your-zhipu-key"
```
## Usage Examples
```bash
# Use GLM-4.7
picoclaw agent -m "你好,请介绍一下自己"
# Code generation
picoclaw agent -m "写一个Python快速排序"
```
## Pricing
Check [bigmodel.cn](https://open.bigmodel.cn) for current pricing.
## See Also
- [Providers Overview](README.md)
- [Configuration Reference](../../configuration/config-file.md)

View file

@ -0,0 +1,136 @@
# Skills Overview
Skills are specialized capabilities that extend PicoClaw's abilities. They provide domain-specific knowledge, commands, and workflows that the agent can use to help you accomplish tasks.
## What are Skills?
A skill is a Markdown file (`SKILL.md`) that contains instructions and examples for the agent. When you ask PicoClaw to perform a task related to a skill, the agent loads that skill's content and follows its guidance.
Skills can include:
- **Command patterns** - Pre-defined shell commands for common tasks
- **API integrations** - Instructions for working with external services
- **Workflows** - Step-by-step procedures for complex operations
- **Domain knowledge** - Specialized information about topics
## Skill Types
### Builtin Skills
PicoClaw comes with builtin skills that are always available:
| Skill | Description |
|-------|-------------|
| `weather` | Get current weather and forecasts (no API key required) |
| `news` | Fetch latest news headlines |
| `stock` | Check stock prices and market data |
| `calculator` | Perform mathematical calculations |
### Community Skills
Install additional skills from GitHub repositories:
```bash
picoclaw skills install sipeed/picoclaw-skills/github
```
### Custom Skills
Create your own skills for specialized workflows:
```
~/.picoclaw/workspace/skills/
my-skill/
SKILL.md
```
## Skill Loading Priority
Skills are loaded from three locations in priority order:
1. **Workspace skills** - `~/.picoclaw/workspace/skills/`
- Project-specific skills, highest priority
- Override global and builtin skills with the same name
2. **Global skills** - `~/.picoclaw/skills/`
- Shared skills across all workspaces
- Override builtin skills with the same name
3. **Builtin skills** - Packaged with PicoClaw
- Always available as fallback
- Can be copied to workspace for customization
## Skill Structure
A skill is a directory containing a `SKILL.md` file:
```
weather/
SKILL.md # Required: skill definition
... # Optional: supporting files
```
The `SKILL.md` file format:
```markdown
---
name: skill-name
description: Brief description of what this skill does
metadata:
key: value
---
# Skill Title
Instructions, commands, and examples for the agent...
```
## Using Skills
Skills are automatically activated when relevant. Just ask PicoClaw:
```
User: "What's the weather in Tokyo?"
Agent: [Uses weather skill]
The current weather in Tokyo is...
```
For more control, see [Using Skills](using-skills.md).
## Managing Skills
### List Installed Skills
```bash
picoclaw skills list
```
### Install from GitHub
```bash
picoclaw skills install sipeed/picoclaw-skills/github
```
### Remove a Skill
```bash
picoclaw skills remove github
```
### View Skill Content
```bash
picoclaw skills show weather
```
## Documentation Sections
- [Using Skills](using-skills.md) - How to use installed skills effectively
- [Installing Skills](installing-skills.md) - Installing skills from GitHub
- [Builtin Skills](builtin-skills.md) - List of builtin skills with examples
- [Creating Skills](creating-skills.md) - How to create custom skills
## See Also
- [CLI Reference: skills](../cli/skills.md)
- [Workspace Structure](../workspace/structure.md)

View file

@ -0,0 +1,286 @@
# Builtin Skills
PicoClaw includes builtin skills that are always available. These cover common tasks and don't require installation.
## Available Builtin Skills
| Skill | Description | Dependencies |
|-------|-------------|--------------|
| `weather` | Get weather information | `curl` |
| `news` | Fetch news headlines | `curl` |
| `stock` | Check stock prices | `curl` |
| `calculator` | Perform calculations | None |
## Weather Skill
Get current weather and forecasts without any API keys.
### Features
- Current conditions for any location
- Multi-day forecasts
- No API key required (uses wttr.in)
- Supports city names, airport codes, and coordinates
### Examples
**Current weather:**
```
User: "What's the weather in London?"
Agent: London: Partly cloudy, +15C
Humidity: 68%, Wind: 12 km/h
```
**Compact format:**
```
User: "Quick weather check for Tokyo"
Agent: Tokyo: Sunny +22C
```
**Full forecast:**
```
User: "Show me the 3-day forecast for New York"
Agent: Weather forecast for New York:
Today Tomorrow Day After
+18C/+12C +20C/+14C +17C/+11C
Partly cloudy Sunny Rain
...
```
**Airport code:**
```
User: "Weather at JFK airport"
Agent: JFK (New York): Clear, +20C
```
### Technical Details
The weather skill uses:
- **wttr.in** - Primary service, text-based weather
- **Open-Meteo** - Fallback for JSON responses
Format options:
- `?format=3` - One-line output
- `?T` - Full terminal forecast
- `?1` - Today only
- `?0` - Current conditions only
## News Skill
Fetch the latest news headlines from various sources.
### Features
- Top headlines
- Category filtering (tech, business, etc.)
- No API key required
- Headline summaries
### Examples
**Top headlines:**
```
User: "Show me today's news"
Agent: Top Headlines:
1. Tech Giants Report Record Q3 Earnings
Major technology companies exceeded analyst expectations...
2. Climate Summit Reaches Historic Agreement
World leaders commit to 50% emissions reduction...
3. New AI Breakthrough in Medical Diagnosis
Researchers announce 99% accuracy in early detection...
```
**Tech news:**
```
User: "What's new in tech?"
Agent: Technology Headlines:
1. Apple Announces New Product Line
2. OpenAI Releases GPT-5 Preview
3. Quantum Computing Milestone Achieved
...
```
## Stock Skill
Check stock prices and market data.
### Features
- Real-time stock prices
- Market indices
- No API key required
- Simple price queries
### Examples
**Stock price:**
```
User: "What's Apple's stock price?"
Agent: AAPL (Apple Inc.): $178.50
Change: +2.30 (+1.31%)
Volume: 52.3M
```
**Market indices:**
```
User: "How's the market doing today?"
Agent: Market Summary:
Dow Jones: 38,500 (+0.5%)
S&P 500: 5,200 (+0.8%)
NASDAQ: 16,400 (+1.2%)
```
**Multiple stocks:**
```
User: "Check prices for AAPL, GOOGL, and MSFT"
Agent: Stock Prices:
AAPL: $178.50 (+1.31%)
GOOGL: $141.25 (+0.85%)
MSFT: $378.90 (+0.92%)
```
## Calculator Skill
Perform mathematical calculations.
### Features
- Basic arithmetic
- Percentages
- Unit conversions
- Compound interest
- No external dependencies
### Examples
**Basic math:**
```
User: "What's 15% of 847?"
Agent: 15% of 847 is 127.05
```
**Compound interest:**
```
User: "Calculate compound interest on $10,000 at 5% for 3 years, compounded monthly"
Agent: Compound Interest Calculation:
Principal: $10,000.00
Rate: 5% annual
Period: 3 years
Compounding: Monthly
Final Amount: $11,614.72
Interest Earned: $1,614.72
```
**Unit conversion:**
```
User: "Convert 100 miles to kilometers"
Agent: 100 miles = 160.934 kilometers
```
**Expression evaluation:**
```
User: "Calculate (25 * 4) + (100 / 5) - 15"
Agent: (25 * 4) + (100 / 5) - 15 = 105
```
## Installing Builtin Skills
To customize builtin skills, copy them to your workspace:
```bash
picoclaw skills install-builtin
```
This copies all builtin skills to `~/.picoclaw/workspace/skills/`, where you can edit them.
### Listing Builtin Skills
View available builtin skills:
```bash
picoclaw skills list-builtin
```
Output:
```
Available Builtin Skills:
-----------------------
weather
Get current weather and forecasts
news
Get latest news headlines
stock
Check stock prices and market data
calculator
Perform mathematical calculations
```
## Customizing Builtin Skills
After installing builtin skills, you can modify them:
```bash
# Install to workspace
picoclaw skills install-builtin
# Edit the weather skill
vim ~/.picoclaw/workspace/skills/weather/SKILL.md
# Your modified version takes precedence
picoclaw skills show weather
```
Common customizations:
- Add local city shortcuts
- Change default format options
- Add new API endpoints
- Include location-specific settings
## Skill Dependencies
Some builtin skills require external tools:
| Skill | Required Tools |
|-------|---------------|
| weather | `curl` |
| news | `curl` |
| stock | `curl` |
| calculator | None (built-in) |
Install dependencies:
```bash
# macOS
brew install curl
# Ubuntu/Debian
sudo apt install curl
```
## See Also
- [Skills Overview](README.md)
- [Using Skills](using-skills.md)
- [Installing Skills](installing-skills.md)
- [Creating Skills](creating-skills.md)

View file

@ -0,0 +1,503 @@
# Creating Skills
Learn how to create custom skills to extend PicoClaw's capabilities.
## Skill Structure
A skill is a directory containing a `SKILL.md` file:
```
~/.picoclaw/workspace/skills/
my-skill/
SKILL.md # Required: skill definition
```
## SKILL.md Format
The skill file uses YAML frontmatter for metadata and Markdown for content:
```markdown
---
name: my-skill
description: Brief description of what this skill does
metadata:
key: value
---
# Skill Title
Instructions for the agent go here.
## Section
More details, commands, and examples...
```
### Frontmatter Fields
| Field | Required | Description |
|-------|----------|-------------|
| `name` | Yes | Skill identifier (alphanumeric with hyphens) |
| `description` | Yes | Brief description (max 1024 characters) |
| `metadata` | No | Additional metadata (JSON object) |
### Naming Rules
- Max 64 characters
- Alphanumeric characters and hyphens only
- Must start with a letter or number
- Examples: `github`, `my-skill`, `api-helper`
## Creating Your First Skill
### Step 1: Create the Directory
```bash
mkdir -p ~/.picoclaw/workspace/skills/hello
```
### Step 2: Create SKILL.md
```bash
cat > ~/.picoclaw/workspace/skills/hello/SKILL.md << 'EOF'
---
name: hello
description: A simple greeting skill that demonstrates skill creation.
---
# Hello Skill
This skill demonstrates basic skill structure.
## Usage
When the user asks for a greeting, respond warmly:
"Hello! I'm your PicoClaw assistant. How can I help you today?"
## Example Commands
Show current time:
```bash
date
```
Show system info:
```bash
uname -a
```
EOF
```
### Step 3: Verify Installation
```bash
picoclaw skills list
```
Output:
```
Installed Skills:
------------------
hello (workspace)
A simple greeting skill that demonstrates skill creation.
```
## Skill Content Best Practices
### 1. Clear Instructions
Write clear, actionable instructions for the agent:
```markdown
# Database Backup Skill
## Purpose
Create backups of PostgreSQL databases.
## Commands
Full backup:
```bash
pg_dump -h localhost -U postgres -d mydb > backup_$(date +%Y%m%d).sql
```
Compressed backup:
```bash
pg_dump -h localhost -U postgres -d mydb | gzip > backup_$(date +%Y%m%d).sql.gz
```
## Important Notes
- Always verify the backup was created
- Store backups in a secure location
- Include timestamp in filename
```
### 2. Include Examples
Provide concrete examples for common use cases:
```markdown
## Examples
Backup specific tables:
```bash
pg_dump -h localhost -U postgres -d mydb -t users -t orders > partial_backup.sql
```
Restore from backup:
```bash
psql -h localhost -U postgres -d mydb < backup_20240115.sql
```
```
### 3. Document Dependencies
List required tools and how to install them:
```markdown
## Requirements
- `curl` - HTTP client
- `jq` - JSON processor
Install on macOS:
```bash
brew install curl jq
```
Install on Ubuntu:
```bash
sudo apt install curl jq
```
```
### 4. Add Error Handling
Include troubleshooting information:
```markdown
## Troubleshooting
### Connection Failed
If you see "Connection refused":
1. Check if PostgreSQL is running: `pg_isready`
2. Verify connection parameters
3. Check firewall settings
### Permission Denied
If you see "Permission denied":
1. Check user has backup privileges
2. Verify .pgpass file is configured
```
## Advanced Skill Features
### API Integration
Create skills that work with APIs:
```markdown
---
name: openai-api
description: Interact with OpenAI API for various AI tasks.
---
# OpenAI API Skill
## Setup
Set your API key:
```bash
export OPENAI_API_KEY="sk-..."
```
## Chat Completion
```bash
curl https://api.openai.com/v1/chat/completions \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-4",
"messages": [{"role": "user", "content": "Hello!"}]
}' | jq .
```
## Image Generation
```bash
curl https://api.openai.com/v1/images/generations \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"prompt": "A sunset over mountains",
"size": "1024x1024"
}' | jq .
```
```
### Workflow Skills
Create skills for multi-step workflows:
```markdown
---
name: deploy
description: Deploy application to production with safety checks.
---
# Deployment Skill
## Pre-deployment Checklist
Before deploying, verify:
1. All tests pass: `npm test`
2. Build succeeds: `npm run build`
3. No security vulnerabilities: `npm audit`
## Deployment Steps
1. Create deployment branch:
```bash
git checkout -b deploy/$(date +%Y%m%d-%H%M)
```
2. Build and test:
```bash
npm ci
npm run build
npm test
```
3. Deploy:
```bash
npm run deploy:production
```
4. Verify deployment:
```bash
curl -s https://api.example.com/health | jq .
```
## Rollback
If issues occur:
```bash
npm run deploy:rollback
```
```
### Tool Requiring Skills
Document external tool requirements:
```markdown
---
name: docker
description: Manage Docker containers and images.
metadata:
requires:
bins: ["docker"]
install:
- id: brew
kind: brew
formula: docker
bins: ["docker"]
- id: apt
kind: apt
package: docker.io
bins: ["docker"]
---
# Docker Skill
## Requirements
Docker must be installed. Install with:
macOS:
```bash
brew install --cask docker
```
Ubuntu:
```bash
sudo apt install docker.io
sudo usermod -aG docker $USER
```
## Common Commands
List containers:
```bash
docker ps -a
```
View logs:
```bash
docker logs <container>
```
Execute in container:
```bash
docker exec -it <container> /bin/sh
```
```
## Testing Your Skill
### 1. List and Verify
```bash
picoclaw skills list
```
Your skill should appear with the correct description.
### 2. Show Content
```bash
picoclaw skills show my-skill
```
Verify the content is displayed correctly.
### 3. Use in Conversation
Start a conversation and test the skill:
```bash
picoclaw agent -m "Use my-skill to help me with something"
```
## Sharing Skills
### Publishing to GitHub
1. Create a GitHub repository:
```
my-picoclaw-skills/
my-skill/
SKILL.md
skills.json
```
2. Create `skills.json` registry:
```json
[
{
"name": "my-skill",
"repository": "username/my-picoclaw-skills/my-skill",
"description": "Description of my skill",
"author": "your-username",
"tags": ["automation", "productivity"]
}
]
```
3. Users can install with:
```bash
picoclaw skills install username/my-picoclaw-skills/my-skill
```
### Contributing to Official Registry
Submit a pull request to the official skills repository:
https://github.com/sipeed/picoclaw-skills
## Skill Templates
### Basic Template
```markdown
---
name: skill-name
description: One-line description of the skill.
---
# Skill Name
Brief introduction to the skill.
## Commands
### Command 1
```bash
command-here
```
### Command 2
```bash
another-command
```
## Examples
Show practical usage examples.
## Troubleshooting
Common issues and solutions.
```
### API Template
```markdown
---
name: api-name
description: Interact with API-NAME service.
---
# API Name Skill
## Authentication
Set API key:
```bash
export API_KEY="your-key-here"
```
## Endpoints
### GET /resource
```bash
curl -H "Authorization: Bearer $API_KEY" \
https://api.example.com/resource
```
### POST /resource
```bash
curl -X POST \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"key": "value"}' \
https://api.example.com/resource
```
```
## Best Practices Summary
1. **Clear naming** - Use descriptive, lowercase names with hyphens
2. **Good descriptions** - Write concise descriptions that explain the skill's purpose
3. **Include examples** - Show how to use commands and features
4. **Document dependencies** - List required tools and installation methods
5. **Add troubleshooting** - Help users solve common problems
6. **Test thoroughly** - Verify your skill works before sharing
7. **Keep it focused** - One skill, one purpose
## See Also
- [Skills Overview](README.md)
- [Using Skills](using-skills.md)
- [Installing Skills](installing-skills.md)
- [Builtin Skills](builtin-skills.md)
- [CLI Reference: skills](../cli/skills.md)

View file

@ -0,0 +1,234 @@
# Installing Skills
Learn how to install and manage skills in PicoClaw.
## Installation Methods
### From GitHub
Install skills directly from GitHub repositories:
```bash
picoclaw skills install <owner>/<repo>/<skill-name>
```
Example:
```bash
picoclaw skills install sipeed/picoclaw-skills/github
```
The installer fetches the `SKILL.md` file from the repository and saves it to your workspace.
### Builtin Skills
Install all builtin skills to your workspace for customization:
```bash
picoclaw skills install-builtin
```
This copies the builtin skills (weather, news, stock, calculator) to `~/.picoclaw/workspace/skills/`, allowing you to modify them.
### Manual Installation
Create a skill manually by creating a directory and `SKILL.md` file:
```bash
mkdir -p ~/.picoclaw/workspace/skills/my-skill
```
Then create `~/.picoclaw/workspace/skills/my-skill/SKILL.md` with your skill content.
## Managing Installed Skills
### List Installed Skills
View all installed skills:
```bash
picoclaw skills list
```
Output shows the skill name, source (workspace/global/builtin), and description:
```
Installed Skills:
------------------
weather (workspace)
Get current weather and forecasts
github (global)
Interact with GitHub using the gh CLI
calculator (builtin)
Perform mathematical calculations
```
### View Skill Details
Display the full content of a skill:
```bash
picoclaw skills show weather
```
Output:
```
Skill: weather
----------------------
# Weather
Two free services, no API keys needed.
## wttr.in (primary)
Quick one-liner:
curl -s "wttr.in/London?format=3"
...
```
### Remove a Skill
Uninstall a skill from your workspace:
```bash
picoclaw skills remove <skill-name>
```
Example:
```bash
picoclaw skills remove github
```
## Searching for Skills
Search the online skill registry for available skills:
```bash
picoclaw skills search
```
Output:
```
Available Skills (5):
--------------------
github
Interact with GitHub using the gh CLI
Repo: sipeed/picoclaw-skills/github
Author: picoclaw
Tags: [git, github, ci]
slack
Send messages to Slack channels
Repo: sipeed/picoclaw-skills/slack
Author: picoclaw
Tags: [slack, messaging]
...
```
## Skill Installation Locations
Skills are installed to different locations based on scope:
| Location | Path | Description |
|----------|------|-------------|
| Workspace | `~/.picoclaw/workspace/skills/` | Project-specific, highest priority |
| Global | `~/.picoclaw/skills/` | Shared across workspaces |
| Builtin | Packaged with PicoClaw | Always available as fallback |
### Choosing Installation Scope
- **Workspace skills** - For skills specific to a project or workflow
- **Global skills** - For skills you want available everywhere
- **Builtin skills** - Ready to use, can be copied for customization
## Installation Examples
### Install from Official Registry
```bash
# Install GitHub integration skill
picoclaw skills install sipeed/picoclaw-skills/github
# Install tmux session management skill
picoclaw skills install sipeed/picoclaw-skills/tmux
```
### Install Custom Skill from Your Repo
```bash
# From your personal GitHub
picoclaw skills install yourname/picoclaw-skills/my-custom-skill
```
### Install All Builtin Skills
```bash
# Copy builtin skills to workspace for customization
picoclaw skills install-builtin
# Now you can edit them
vim ~/.picoclaw/workspace/skills/weather/SKILL.md
```
## Updating Skills
Skills don't auto-update. To update a skill:
```bash
# Remove old version
picoclaw skills remove weather
# Reinstall from source
picoclaw skills install sipeed/picoclaw-skills/weather
```
## GitHub Repository Structure
Skill repositories should have this structure:
```
picoclaw-skills/
weather/
SKILL.md
github/
SKILL.md
skills.json # Optional: registry file
```
The `SKILL.md` file must be at the root of the skill directory.
## Troubleshooting
### Installation Fails
Common causes:
1. **Network error** - Check your internet connection
2. **Repository not found** - Verify the repository path
3. **Skill already exists** - Remove the existing skill first
```bash
# Remove and reinstall
picoclaw skills remove <name>
picoclaw skills install <repo>
```
### Skill Not Loading After Install
1. Verify installation: `picoclaw skills list`
2. Check file exists: `ls ~/.picoclaw/workspace/skills/<name>/SKILL.md`
3. Validate skill format: `picoclaw skills show <name>`
### Permission Denied
Ensure you have write permissions to the skills directory:
```bash
ls -la ~/.picoclaw/workspace/skills/
```
## See Also
- [Skills Overview](README.md)
- [Using Skills](using-skills.md)
- [Builtin Skills](builtin-skills.md)
- [Creating Skills](creating-skills.md)
- [CLI Reference: skills](../cli/skills.md)

View file

@ -0,0 +1,205 @@
# Using Skills
Learn how to effectively use installed skills in PicoClaw.
## How Skills Work
When you interact with PicoClaw, it automatically loads relevant skills based on your request. The skill content is added to the agent's context, providing it with specialized knowledge and command patterns.
## Automatic Skill Activation
Skills are activated automatically based on context. PicoClaw analyzes your request and loads skills that might be relevant:
```
User: "What's the weather like in San Francisco?"
Agent: [Loads weather skill, executes curl command]
The current weather in San Francisco is partly cloudy
with a temperature of 18C (64F). Humidity is at 72%.
```
## Viewing Available Skills
List all installed skills to see what capabilities are available:
```bash
picoclaw skills list
```
Output:
```
Installed Skills:
------------------
weather (workspace)
Get current weather and forecasts (no API key required)
github (global)
Interact with GitHub using the gh CLI
calculator (builtin)
Perform mathematical calculations
```
## Viewing Skill Details
To see the full content of a skill:
```bash
picoclaw skills show weather
```
This displays the skill's instructions, commands, and examples that the agent uses.
## Skill Examples
### Weather Skill
The weather skill uses wttr.in for weather data without requiring an API key.
```
User: "Check the weather in London"
Agent: [Uses weather skill]
London: Partly cloudy, +15C
Humidity: 68%, Wind: 12 km/h NW
```
```
User: "Get a 3-day forecast for Tokyo"
Agent: [Uses weather skill]
Here's the forecast for Tokyo...
Morning Noon Evening
+12C +18C +14C
Rain Cloudy Clear
...
```
### GitHub Skill
The GitHub skill provides GitHub CLI integration.
```
User: "List open issues in my repo"
Agent: [Uses github skill]
Here are the open issues:
#142 - Fix authentication bug
#141 - Add dark mode support
#140 - Update documentation
```
```
User: "Check the CI status of PR 55"
Agent: [Uses github skill]
PR #55 CI Status: All checks passed
- build: passed
- test: passed
- lint: passed
```
### Calculator Skill
The calculator skill performs mathematical calculations.
```
User: "What's 15% of 847?"
Agent: [Uses calculator skill]
15% of 847 is 127.05
```
```
User: "Calculate the compound interest on $10,000 at 5% for 3 years"
Agent: [Uses calculator skill]
After 3 years at 5% annual interest:
Final amount: $11,576.25
Total interest earned: $1,576.25
```
### News Skill
The news skill fetches current headlines.
```
User: "Show me today's top headlines"
Agent: [Uses news skill]
Top Headlines:
1. Tech Giants Report Q3 Earnings
2. Climate Summit Reaches Agreement
3. New AI Breakthrough Announced
...
```
## Explicit Skill Requests
You can explicitly mention a skill to ensure it's used:
```
User: "Use the github skill to create a new issue about the login bug"
Agent: [Uses github skill, creates issue]
Created issue #143: "Login bug on mobile devices"
https://github.com/owner/repo/issues/143
```
## Skill Context in Conversations
Skills remain active throughout a conversation session. If you start talking about weather, the weather skill stays in context for follow-up questions:
```
User: "What's the weather in Paris?"
Agent: Paris: Sunny, +22C
User: "And in Berlin?"
Agent: [Weather skill still active]
Berlin: Cloudy, +18C
User: "Which is warmer?"
Agent: Paris is warmer at +22C compared to Berlin's +18C.
```
## Tips for Using Skills
1. **Be specific** - Clear requests help the agent select the right skill
2. **Check skill content** - Use `picoclaw skills show <name>` to see what a skill can do
3. **Combine skills** - Complex tasks may use multiple skills together
4. **Customize** - Copy builtin skills to your workspace to modify them
## Troubleshooting
### Skill Not Activating
If a skill isn't being used:
1. Verify it's installed: `picoclaw skills list`
2. Check the skill content: `picoclaw skills show <name>`
3. Try being more explicit: "Use the weather skill to..."
### Skill Commands Failing
Some skills require external tools:
1. Check dependencies in the skill description
2. Install required tools (e.g., `gh` CLI for GitHub skill)
3. Ensure tools are in your PATH
### Outdated Skill
To update a skill:
```bash
picoclaw skills remove <name>
picoclaw skills install <repo>
```
## See Also
- [Skills Overview](README.md)
- [Installing Skills](installing-skills.md)
- [Builtin Skills](builtin-skills.md)
- [Creating Skills](creating-skills.md)

View file

@ -0,0 +1,147 @@
# Tools Overview
PicoClaw has built-in tools that allow the agent to interact with files, execute commands, search the web, and more.
## Available Tools
### File System Tools
| Tool | Description |
|------|-------------|
| `read_file` | Read file contents |
| `write_file` | Create or overwrite files |
| `list_dir` | List directory contents |
| `edit_file` | Replace text in files |
| `append_file` | Append to files |
### Execution Tools
| Tool | Description |
|------|-------------|
| `exec` | Execute shell commands |
### Web Tools
| Tool | Description |
|------|-------------|
| `web_search` | Search the web |
| `web_fetch` | Fetch web page content |
### Communication Tools
| Tool | Description |
|------|-------------|
| `message` | Send messages to channels |
| `spawn` | Create subagents for background tasks |
### Scheduling Tools
| Tool | Description |
|------|-------------|
| `cron` | Schedule reminders and tasks |
### Hardware Tools (Linux only)
| Tool | Description |
|------|-------------|
| `i2c` | I2C bus interaction |
| `spi` | SPI bus interaction |
## Tool Security
### Workspace Restriction
When `restrict_to_workspace: true` (default):
- File tools only work within workspace
- Exec commands run in workspace directory
- Symlink escapes are blocked
### Exec Protection
Even with workspace restriction disabled, these commands are blocked:
- `rm -rf`, `del /f`, `rmdir /s`
- `format`, `mkfs`, `diskpart`
- `dd if=`
- `shutdown`, `reboot`, `poweroff`
- Fork bombs
## Tool Configuration
### Web Search
Configure search providers:
```json
{
"tools": {
"web": {
"brave": {
"enabled": true,
"api_key": "YOUR_KEY",
"max_results": 5
},
"duckduckgo": {
"enabled": true,
"max_results": 5
}
}
}
}
```
### Exec
Configure command restrictions:
```json
{
"tools": {
"exec": {
"enable_deny_patterns": true,
"custom_deny_patterns": ["wget.*", "curl.*"]
}
}
}
```
### Cron
Configure job timeout:
```json
{
"tools": {
"cron": {
"exec_timeout_minutes": 5
}
}
}
```
## Using Tools
The agent automatically uses tools based on your requests:
```
User: "Read the file notes.txt and summarize it"
Agent: [Uses read_file tool]
The file contains...
```
## Tool Details
- [File System Tools](filesystem.md)
- [Exec Tool](exec.md)
- [Web Tools](web.md)
- [Messaging Tool](messaging.md)
- [Spawn Tool](spawn.md)
- [Cron Tool](cron.md)
- [Hardware Tools](hardware.md)
## See Also
- [Security Sandbox](../advanced/security-sandbox.md)
- [Configuration Reference](../../configuration/config-file.md)

View file

@ -0,0 +1,197 @@
# Cron Tool
Schedule reminders and recurring tasks.
## Tool
### cron
Schedule, list, or manage scheduled jobs.
**Parameters:**
| Name | Type | Required | Description |
|------|------|----------|-------------|
| `action` | string | Yes | Action: `add`, `list`, `remove`, `enable`, `disable` |
| `name` | string | Conditional | Job name (for add) |
| `message` | string | Conditional | Message for agent (for add) |
| `every_seconds` | int | Conditional | Run every N seconds |
| `at_seconds` | int | Conditional | Run once after N seconds |
| `cron_expr` | string | Conditional | Cron expression |
| `job_id` | string | Conditional | Job ID (for remove/enable/disable) |
**Examples:**
```json
// Add recurring job
{
"action": "add",
"name": "Hourly check",
"message": "Check system status",
"every_seconds": 3600
}
// Add one-time reminder
{
"action": "add",
"name": "Meeting reminder",
"message": "Time for your meeting!",
"at_seconds": 300
}
// List all jobs
{
"action": "list"
}
// Remove a job
{
"action": "remove",
"job_id": "abc123"
}
```
## CLI vs Tool
### CLI Commands
Use CLI for administrative tasks:
```bash
picoclaw cron list
picoclaw cron add -n "name" -m "message" -e 3600
picoclaw cron remove <job_id>
```
### Tool Usage
The agent uses the cron tool when you ask:
```
User: "Remind me to take a break in 30 minutes"
Agent uses cron tool:
{
"action": "add",
"name": "Break reminder",
"message": "Time to take a break!",
"at_seconds": 1800
}
Agent: "I'll remind you to take a break in 30 minutes."
```
## Schedule Types
### One-Time (at_seconds)
Run once after N seconds:
```json
{
"action": "add",
"name": "Reminder",
"message": "Meeting in 10 minutes!",
"at_seconds": 600
}
```
### Recurring (every_seconds)
Run every N seconds:
```json
{
"action": "add",
"name": "Hourly check",
"message": "Check the time",
"every_seconds": 3600
}
```
### Cron Expression
Use standard cron format:
```json
{
"action": "add",
"name": "Daily standup",
"message": "Time for standup!",
"cron_expr": "0 9 * * 1-5"
}
```
## Cron Expressions
```
┌───────────── minute (0 - 59)
│ ┌───────────── hour (0 - 23)
│ │ ┌───────────── day of month (1 - 31)
│ │ │ ┌───────────── month (1 - 12)
│ │ │ │ ┌───────────── day of week (0 - 6)
│ │ │ │ │
* * * * *
```
| Expression | Meaning |
|------------|---------|
| `0 9 * * *` | Daily at 9:00 AM |
| `0 */2 * * *` | Every 2 hours |
| `30 8 * * 1-5` | Weekdays at 8:30 AM |
| `0 0 * * 0` | Every Sunday midnight |
## Configuration
### Timeout
Set max execution time for jobs:
```json
{
"tools": {
"cron": {
"exec_timeout_minutes": 5
}
}
}
```
## Storage
Jobs are stored in:
```
~/.picoclaw/workspace/cron/jobs.json
```
## Examples
```
User: "Remind me every hour to drink water"
Agent uses cron tool:
{
"action": "add",
"name": "Hydration reminder",
"message": "Time to drink some water!",
"every_seconds": 3600
}
```
```
User: "Set a reminder for my 3 PM meeting"
Agent uses cron tool:
{
"action": "add",
"name": "Meeting reminder",
"message": "Your meeting starts in 10 minutes!",
"at_seconds": <calculated seconds to 2:50 PM>
}
```
## See Also
- [CLI Cron Commands](../cli/cron.md)
- [Heartbeat Tasks](../workspace/heartbeat-tasks.md)

View file

@ -0,0 +1,147 @@
# Exec Tool
Execute shell commands from within the agent.
## Tool
### exec
Execute a shell command.
**Parameters:**
| Name | Type | Required | Description |
|------|------|----------|-------------|
| `command` | string | Yes | Shell command to execute |
**Example:**
```json
{
"command": "ls -la"
}
```
## Security
### Workspace Restriction
When `restrict_to_workspace: true`:
- Commands execute within workspace directory
- Path arguments must be within workspace
### Deny Patterns
Dangerous commands are always blocked:
| Pattern | Reason |
|---------|--------|
| `rm -rf`, `rmdir /s` | Bulk deletion |
| `format`, `mkfs` | Disk formatting |
| `dd if=` | Disk imaging |
| `shutdown`, `reboot` | System control |
| `:(){ :\|:& };:` | Fork bomb |
| `wget`, `curl` (configurable) | Network downloads |
### Custom Deny Patterns
Add your own blocked patterns:
```json
{
"tools": {
"exec": {
"enable_deny_patterns": true,
"custom_deny_patterns": [
"apt.*",
"yum.*",
"pip.*"
]
}
}
}
```
## Timeout
Commands have a 60-second timeout by default. Long-running commands will be terminated.
## Usage Examples
### List Files
```
User: "Show me all Python files"
Agent uses exec:
{
"command": "find . -name '*.py'"
}
Agent: "Found 3 Python files:
- main.py
- utils.py
- test.py"
```
### Git Operations
```
User: "What's the current git status?"
Agent uses exec:
{
"command": "git status"
}
Agent: "On branch main, working tree clean."
```
### Process Information
```
User: "How much disk space is free?"
Agent uses exec:
{
"command": "df -h ."
}
Agent: "You have 50GB free of 100GB total."
```
## Error Handling
```
User: "Run make build"
Agent uses exec:
{
"command": "make build"
}
If command fails:
Agent: "The command failed with exit code 1. Error: make: *** No targets specified."
```
## Disabling Restriction
For trusted environments:
```json
{
"agents": {
"defaults": {
"restrict_to_workspace": false
}
}
}
```
**Warning**: This allows running any command the user can execute.
## See Also
- [Tools Overview](README.md)
- [Security Sandbox](../advanced/security-sandbox.md)

View file

@ -0,0 +1,169 @@
# File System Tools
File system tools allow the agent to read, write, and manage files.
## Tools
### read_file
Read the contents of a file.
**Parameters:**
| Name | Type | Required | Description |
|------|------|----------|-------------|
| `path` | string | Yes | File path (relative to workspace) |
**Example:**
```json
{
"path": "notes.txt"
}
```
### write_file
Create or overwrite a file with content.
**Parameters:**
| Name | Type | Required | Description |
|------|------|----------|-------------|
| `path` | string | Yes | File path (relative to workspace) |
| `content` | string | Yes | File content |
**Example:**
```json
{
"path": "output.txt",
"content": "Hello, World!"
}
```
### list_dir
List contents of a directory.
**Parameters:**
| Name | Type | Required | Description |
|------|------|----------|-------------|
| `path` | string | Yes | Directory path (relative to workspace) |
**Example:**
```json
{
"path": "."
}
```
### edit_file
Replace text in a file.
**Parameters:**
| Name | Type | Required | Description |
|------|------|----------|-------------|
| `path` | string | Yes | File path (relative to workspace) |
| `old_text` | string | Yes | Text to replace |
| `new_text` | string | Yes | Replacement text |
**Example:**
```json
{
"path": "config.json",
"old_text": "\"enabled\": false",
"new_text": "\"enabled\": true"
}
```
### append_file
Append content to a file.
**Parameters:**
| Name | Type | Required | Description |
|------|------|----------|-------------|
| `path` | string | Yes | File path (relative to workspace) |
| `content` | string | Yes | Content to append |
**Example:**
```json
{
"path": "log.txt",
"content": "\nNew log entry"
}
```
## Security
### Workspace Restriction
When `restrict_to_workspace: true`:
- All paths are relative to workspace
- Absolute paths outside workspace are blocked
- Symlink escapes are prevented
### Path Resolution
Paths are resolved relative to the workspace:
| Input | Resolved To |
|-------|-------------|
| `file.txt` | `~/workspace/file.txt` |
| `subdir/file.txt` | `~/workspace/subdir/file.txt` |
| `/etc/passwd` | **BLOCKED** (outside workspace) |
## Usage Examples
```
User: "Read the README.md file"
Agent uses read_file:
{
"path": "README.md"
}
Agent: "The README.md file contains..."
```
```
User: "Create a todo list file"
Agent uses write_file:
{
"path": "todo.md",
"content": "# Todo List\n\n- [ ] Task 1\n- [ ] Task 2"
}
Agent: "Created todo.md with your todo list."
```
## Disabling Restriction
For trusted environments:
```json
{
"agents": {
"defaults": {
"restrict_to_workspace": false
}
}
}
```
**Warning**: This allows access to any file the user can access.
## See Also
- [Tools Overview](README.md)
- [Security Sandbox](../advanced/security-sandbox.md)

View file

@ -0,0 +1,201 @@
# Hardware Tools
Interact with hardware devices via I2C and SPI buses. (Linux only)
## Prerequisites
- Linux operating system
- Appropriate permissions (usually root or i2c/spi group)
- Enabled hardware interfaces
## I2C Tool
### i2c
Interact with I2C bus devices.
**Parameters:**
| Name | Type | Required | Description |
|------|------|----------|-------------|
| `action` | string | Yes | Action: `detect`, `scan`, `read`, `write` |
| `bus` | int | Conditional | Bus number |
| `address` | string | Conditional | Device address (hex) |
| `register` | string | Conditional | Register address (hex) |
| `data` | string | Conditional | Data to write (hex) |
**Actions:**
### detect
List available I2C buses:
```json
{
"action": "detect"
}
```
### scan
Scan bus for devices:
```json
{
"action": "scan",
"bus": 1
}
```
### read
Read from device register:
```json
{
"action": "read",
"bus": 1,
"address": "0x76",
"register": "0x00"
}
```
### write
Write to device register:
```json
{
"action": "write",
"bus": 1,
"address": "0x76",
"register": "0x00",
"data": "0xAA"
}
```
## SPI Tool
### spi
Interact with SPI bus devices.
**Parameters:**
| Name | Type | Required | Description |
|------|------|----------|-------------|
| `action` | string | Yes | Action: `list`, `transfer`, `read` |
| `device` | string | Conditional | SPI device path |
| `data` | string | Conditional | Data to transfer (hex) |
**Actions:**
### list
List available SPI devices:
```json
{
"action": "list"
}
```
### transfer
Send and receive data:
```json
{
"action": "transfer",
"device": "/dev/spidev0.0",
"data": "0xAA 0xBB 0xCC"
}
```
### read
Read data from device:
```json
{
"action": "read",
"device": "/dev/spidev0.0"
}
```
## Setup (Linux)
### Enable I2C
```bash
# Raspberry Pi
sudo raspi-config
# Interface Options -> I2C -> Enable
# Add user to i2c group
sudo usermod -aG i2c $USER
```
### Enable SPI
```bash
# Raspberry Pi
sudo raspi-config
# Interface Options -> SPI -> Enable
# Add user to spi group
sudo usermod -aG spi $USER
```
### Install Tools
```bash
# Debian/Ubuntu
sudo apt install i2c-tools spi-tools
```
## Common Devices
### I2C Sensors
| Device | Address | Description |
|--------|---------|-------------|
| BME280 | 0x76, 0x77 | Temperature, humidity, pressure |
| MPU6050 | 0x68 | Accelerometer, gyroscope |
| SSD1306 | 0x3C | OLED display |
### SPI Devices
| Device | Description |
|--------|-------------|
| W25Q32 | Flash memory |
| MFRC522 | RFID reader |
| ILI9341 | TFT display |
## Example: Read BME280
```
User: "Read temperature from the BME280 sensor"
Agent uses i2c tool:
{
"action": "scan",
"bus": 1
}
Finds device at 0x76, then:
{
"action": "read",
"bus": 1,
"address": "0x76",
"register": "0xFA"
}
Agent: "Temperature reading: 23.5°C"
```
## See Also
- [Tools Overview](README.md)
- [MaixCam Channel](../channels/maixcam.md)

View file

@ -0,0 +1,120 @@
# Messaging Tool
Send messages to users through configured channels.
## Tool
### message
Send a message to a specific channel and recipient.
**Parameters:**
| Name | Type | Required | Description |
|------|------|----------|-------------|
| `channel` | string | Yes | Channel name (telegram, discord, etc.) |
| `chat_id` | string | Yes | Chat/user ID |
| `content` | string | Yes | Message content |
**Example:**
```json
{
"channel": "telegram",
"chat_id": "123456789",
"content": "Task completed successfully!"
}
```
## Use Cases
### Notifications
Send notifications from scheduled tasks:
```markdown
# HEARTBEAT.md
- Every hour, check server status
- If issues found, send message via telegram
```
### Subagent Responses
Subagents use the message tool to communicate results:
```
Subagent: [Uses message tool]
{
"channel": "telegram",
"chat_id": "123456789",
"content": "Research complete! Here's the summary..."
}
```
### Alerts
Send alerts based on conditions:
```
Agent: "I found an important update. Sending notification..."
[Uses message tool]
```
## Channel Support
| Channel | Supports message tool |
|---------|----------------------|
| Telegram | Yes |
| Discord | Yes |
| Slack | Yes |
| LINE | Yes |
| QQ | Yes |
| DingTalk | Yes |
| OneBot | Yes |
## Finding Chat IDs
### Telegram
1. Send a message to your bot
2. Visit: `https://api.telegram.org/bot<TOKEN>/getUpdates`
3. Find `chat.id` in the response
Or use @userinfobot to get your user ID.
### Discord
1. Enable Developer Mode in Discord settings
2. Right-click a channel or user
3. Select "Copy ID"
### Slack
User IDs start with `U`, channel IDs start with `C`.
## Examples
```
User (via Telegram): "Let me know when the build finishes"
Agent spawns subagent for async task...
Subagent uses message tool:
{
"channel": "telegram",
"chat_id": "123456789",
"content": "Build finished successfully! All tests passed."
}
```
## Security
The message tool can only send to:
- Channels that are enabled
- Chat IDs that have interacted with the bot
## See Also
- [Spawn Tool](spawn.md)
- [Channels Overview](../channels/README.md)

View file

@ -0,0 +1,147 @@
# Spawn Tool
Create subagents to handle background tasks asynchronously.
## Tool
### spawn
Spawn a subagent to execute a task independently.
**Parameters:**
| Name | Type | Required | Description |
|------|------|----------|-------------|
| `prompt` | string | Yes | Task for the subagent |
| `agent_id` | string | No | Specific agent to use |
**Example:**
```json
{
"prompt": "Search for the latest AI news and summarize the top 3 stories"
}
```
## How Spawn Works
1. Main agent spawns a subagent with a task
2. Main agent continues immediately (non-blocking)
3. Subagent works independently with its own context
4. Subagent uses `message` tool to report results
5. User receives the result directly
## Use Cases
### Long-Running Tasks
Don't block the main conversation:
```
User: "Search for information about quantum computing and write a summary"
Agent spawns subagent:
{
"prompt": "Research quantum computing thoroughly and send a comprehensive summary to the user via message tool"
}
Agent: "I've started researching quantum computing. I'll send you the summary when complete."
```
### Heartbeat Tasks
For periodic tasks that might take time:
```markdown
# HEARTBEAT.md
## Use spawn for long tasks
- Spawn to search AI news and send summary
- Spawn to check weather and alert if rain expected
```
### Parallel Tasks
Multiple tasks at once:
```
User: "Check stock prices for AAPL, GOOGL, and MSFT"
Agent spawns multiple subagents for parallel processing.
```
## Subagent Capabilities
Subagents have access to:
- All tools (file, web, exec, etc.)
- Message tool to communicate with user
- Same workspace restrictions
Subagents do NOT have:
- Access to main conversation history
- Ability to spawn more subagents (by default)
## Configuration
### Allowed Subagents
Restrict which agents can be spawned:
```json
{
"agents": {
"list": [
{
"id": "main",
"subagents": {
"allow_agents": ["researcher", "coder"]
}
}
]
}
}
```
### Subagent Model
Use a different model for subagents:
```json
{
"agents": {
"list": [
{
"id": "main",
"subagents": {
"model": "gpt-4o-mini"
}
}
]
}
}
```
## Example Flow
```
1. User: "Research AI trends and report back"
2. Main agent spawns subagent with prompt
3. Main agent responds: "Research started. I'll update you when done."
4. User continues chatting with main agent
5. Subagent completes research
6. Subagent uses message tool to send results
7. User receives: "AI Trends Report: [comprehensive summary]"
```
## See Also
- [Messaging Tool](messaging.md)
- [Heartbeat Tasks](../workspace/heartbeat-tasks.md)
- [Multi-Agent System](../advanced/multi-agent.md)

Some files were not shown because too many files have changed in this diff Show more