copaw-ai-assistant
Personal AI assistant framework supporting multiple chat channels (DingTalk, Feishu, QQ, Discord, etc.) with extensible skills, local/cloud deployment, and cron scheduling.
Best use case
copaw-ai-assistant is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Personal AI assistant framework supporting multiple chat channels (DingTalk, Feishu, QQ, Discord, etc.) with extensible skills, local/cloud deployment, and cron scheduling.
Teams using copaw-ai-assistant should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/copaw-ai-assistant/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How copaw-ai-assistant Compares
| Feature / Agent | copaw-ai-assistant | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Personal AI assistant framework supporting multiple chat channels (DingTalk, Feishu, QQ, Discord, etc.) with extensible skills, local/cloud deployment, and cron scheduling.
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# CoPaw AI Assistant Skill
> Skill by [ara.so](https://ara.so) — Daily 2026 Skills collection.
CoPaw is a personal AI assistant framework you deploy on your own machine or in the cloud. It connects to multiple chat platforms (DingTalk, Feishu, QQ, Discord, iMessage, Telegram, Mattermost, Matrix, MQTT) through a single agent, supports custom Python skills, scheduled cron jobs, local and cloud LLMs, and provides a web Console at `http://127.0.0.1:8088/`.
---
## Installation
### pip (recommended if Python 3.10–3.13 is available)
```bash
pip install copaw
copaw init --defaults # non-interactive setup with sensible defaults
copaw app # starts the web Console + backend
```
### Script install (no Python setup required)
**macOS / Linux:**
```bash
curl -fsSL https://copaw.agentscope.io/install.sh | bash
# With Ollama support:
curl -fsSL https://copaw.agentscope.io/install.sh | bash -s -- --extras ollama
# Multiple extras:
curl -fsSL https://copaw.agentscope.io/install.sh | bash -s -- --extras ollama,llamacpp
```
**Windows CMD:**
```cmd
curl -fsSL https://copaw.agentscope.io/install.bat -o install.bat && install.bat
```
**Windows PowerShell:**
```powershell
irm https://copaw.agentscope.io/install.ps1 | iex
```
After script install, open a new terminal:
```bash
copaw init --defaults
copaw app
```
### Install from source
```bash
git clone https://github.com/agentscope-ai/CoPaw.git
cd CoPaw
pip install -e ".[dev]"
copaw init --defaults
copaw app
```
---
## CLI Reference
```bash
copaw init # interactive workspace setup
copaw init --defaults # non-interactive setup
copaw app # start the Console (http://127.0.0.1:8088/)
copaw app --port 8090 # use a custom port
copaw --help # list all commands
```
---
## Workspace Structure
After `copaw init`, a workspace is created (default: `~/.copaw/workspace/`):
```
~/.copaw/workspace/
├── config.yaml # agent, provider, channel configuration
├── skills/ # custom skill files (auto-loaded)
│ └── my_skill.py
├── memory/ # conversation memory storage
└── logs/ # runtime logs
```
---
## Configuration (`config.yaml`)
`copaw init` generates this file. Edit it directly or use the Console UI.
### LLM Provider (OpenAI-compatible)
```yaml
providers:
- id: openai-main
type: openai
api_key: ${OPENAI_API_KEY} # use env var reference
model: gpt-4o
base_url: https://api.openai.com/v1
- id: local-ollama
type: ollama
model: llama3.2
base_url: http://localhost:11434
```
### Agent Settings
```yaml
agent:
name: CoPaw
language: en # en, zh, ja, etc.
provider_id: openai-main
context_limit: 8000
```
### Channel: DingTalk
```yaml
channels:
- type: dingtalk
app_key: ${DINGTALK_APP_KEY}
app_secret: ${DINGTALK_APP_SECRET}
agent_id: ${DINGTALK_AGENT_ID}
mention_only: true # only respond when @mentioned in groups
```
### Channel: Feishu (Lark)
```yaml
channels:
- type: feishu
app_id: ${FEISHU_APP_ID}
app_secret: ${FEISHU_APP_SECRET}
mention_only: false
```
### Channel: Discord
```yaml
channels:
- type: discord
token: ${DISCORD_BOT_TOKEN}
mention_only: true
```
### Channel: Telegram
```yaml
channels:
- type: telegram
token: ${TELEGRAM_BOT_TOKEN}
```
### Channel: QQ
```yaml
channels:
- type: qq
uin: ${QQ_UIN}
password: ${QQ_PASSWORD}
```
### Channel: Mattermost
```yaml
channels:
- type: mattermost
url: ${MATTERMOST_URL}
token: ${MATTERMOST_TOKEN}
team: my-team
```
### Channel: Matrix
```yaml
channels:
- type: matrix
homeserver: ${MATRIX_HOMESERVER}
user_id: ${MATRIX_USER_ID}
access_token: ${MATRIX_ACCESS_TOKEN}
```
---
## Custom Skills
Skills are Python files placed in `~/.copaw/workspace/skills/`. They are **auto-loaded** when CoPaw starts — no registration step needed.
### Minimal skill structure
```python
# ~/.copaw/workspace/skills/weather.py
SKILL_NAME = "get_weather"
SKILL_DESCRIPTION = "Get current weather for a city"
# Tool schema (OpenAI function-calling format)
SKILL_SCHEMA = {
"type": "function",
"function": {
"name": SKILL_NAME,
"description": SKILL_DESCRIPTION,
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "City name, e.g. 'Tokyo'"
}
},
"required": ["city"]
}
}
}
def get_weather(city: str) -> str:
"""Fetch weather data for the given city."""
import os
import requests
api_key = os.environ["OPENWEATHER_API_KEY"]
url = f"https://api.openweathermap.org/data/2.5/weather"
resp = requests.get(url, params={"q": city, "appid": api_key, "units": "metric"})
resp.raise_for_status()
data = resp.json()
temp = data["main"]["temp"]
desc = data["weather"][0]["description"]
return f"{city}: {temp}°C, {desc}"
```
### Skill with async support
```python
# ~/.copaw/workspace/skills/summarize_url.py
SKILL_NAME = "summarize_url"
SKILL_DESCRIPTION = "Fetch and summarize the content of a URL"
SKILL_SCHEMA = {
"type": "function",
"function": {
"name": SKILL_NAME,
"description": SKILL_DESCRIPTION,
"parameters": {
"type": "object",
"properties": {
"url": {"type": "string", "description": "The URL to summarize"}
},
"required": ["url"]
}
}
}
async def summarize_url(url: str) -> str:
import httpx
async with httpx.AsyncClient(timeout=15) as client:
resp = await client.get(url)
text = resp.text[:4000] # truncate for context limit
return f"Content preview from {url}:\n{text}"
```
### Skill returning structured data
```python
# ~/.copaw/workspace/skills/list_files.py
import os
import json
SKILL_NAME = "list_files"
SKILL_DESCRIPTION = "List files in a directory"
SKILL_SCHEMA = {
"type": "function",
"function": {
"name": SKILL_NAME,
"description": SKILL_DESCRIPTION,
"parameters": {
"type": "object",
"properties": {
"path": {
"type": "string",
"description": "Absolute or relative directory path"
},
"extension": {
"type": "string",
"description": "Filter by extension, e.g. '.py'. Optional."
}
},
"required": ["path"]
}
}
}
def list_files(path: str, extension: str = "") -> str:
entries = os.listdir(os.path.expanduser(path))
if extension:
entries = [e for e in entries if e.endswith(extension)]
return json.dumps(sorted(entries))
```
---
## Cron / Scheduled Tasks
Define cron jobs in `config.yaml` to run skills on a schedule and push results to a channel:
```yaml
cron:
- id: daily-digest
schedule: "0 8 * * *" # every day at 08:00
skill: get_weather
skill_args:
city: "Tokyo"
channel_id: dingtalk-main # matches a channel id below
message_template: "Good morning! Today's weather: {result}"
- id: hourly-news
schedule: "0 * * * *"
skill: fetch_tech_news
channel_id: discord-main
```
---
## Local Model Setup
### Ollama
```bash
# Install Ollama: https://ollama.ai
ollama pull llama3.2
ollama serve # starts on http://localhost:11434
```
```yaml
# config.yaml
providers:
- id: ollama-local
type: ollama
model: llama3.2
base_url: http://localhost:11434
```
### LM Studio
```yaml
providers:
- id: lmstudio-local
type: lmstudio
model: lmstudio-community/Meta-Llama-3-8B-Instruct-GGUF
base_url: http://localhost:1234/v1
```
### llama.cpp (extra required)
```bash
pip install "copaw[llamacpp]"
```
```yaml
providers:
- id: llamacpp-local
type: llamacpp
model_path: /path/to/model.gguf
```
---
## Tool Guard (Security)
Tool Guard blocks risky tool calls and requires user approval before execution. Configure in `config.yaml`:
```yaml
agent:
tool_guard:
enabled: true
risk_patterns:
- "rm -rf"
- "DROP TABLE"
- "os.system"
auto_approve_low_risk: true
```
When a call is blocked, the Console shows an approval prompt. The user can approve or deny before the tool runs.
---
## Token Usage Tracking
Token usage is tracked automatically and visible in the Console dashboard. Access programmatically:
```python
# In a skill or debug script
from copaw.telemetry import get_usage_summary
summary = get_usage_summary()
print(summary)
# {'total_tokens': 142300, 'prompt_tokens': 98200, 'completion_tokens': 44100, 'by_provider': {...}}
```
---
## Environment Variables
Set these before running `copaw app`, or reference them in `config.yaml` as `${VAR_NAME}`:
```bash
# LLM providers
export OPENAI_API_KEY=...
export ANTHROPIC_API_KEY=...
# Channels
export DINGTALK_APP_KEY=...
export DINGTALK_APP_SECRET=...
export DINGTALK_AGENT_ID=...
export FEISHU_APP_ID=...
export FEISHU_APP_SECRET=...
export DISCORD_BOT_TOKEN=...
export TELEGRAM_BOT_TOKEN=...
export QQ_UIN=...
export QQ_PASSWORD=...
export MATTERMOST_URL=...
export MATTERMOST_TOKEN=...
export MATRIX_HOMESERVER=...
export MATRIX_USER_ID=...
export MATRIX_ACCESS_TOKEN=...
# Custom skill secrets
export OPENWEATHER_API_KEY=...
```
---
## Common Patterns
### Pattern: Morning briefing to DingTalk
```yaml
# config.yaml excerpt
channels:
- id: dingtalk-main
type: dingtalk
app_key: ${DINGTALK_APP_KEY}
app_secret: ${DINGTALK_APP_SECRET}
agent_id: ${DINGTALK_AGENT_ID}
cron:
- id: morning-brief
schedule: "30 7 * * 1-5" # weekdays 07:30
skill: daily_briefing
channel_id: dingtalk-main
```
```python
# skills/daily_briefing.py
SKILL_NAME = "daily_briefing"
SKILL_DESCRIPTION = "Compile a morning briefing with weather and news"
SKILL_SCHEMA = {
"type": "function",
"function": {
"name": SKILL_NAME,
"description": SKILL_DESCRIPTION,
"parameters": {"type": "object", "properties": {}, "required": []}
}
}
def daily_briefing() -> str:
import os, requests, datetime
today = datetime.date.today().strftime("%A, %B %d")
# Add your own data sources here
return f"Good morning! Today is {today}. Have a productive day!"
```
### Pattern: Multi-channel broadcast
```python
# skills/broadcast.py
SKILL_NAME = "broadcast_message"
SKILL_DESCRIPTION = "Send a message to all configured channels"
SKILL_SCHEMA = {
"type": "function",
"function": {
"name": SKILL_NAME,
"description": SKILL_DESCRIPTION,
"parameters": {
"type": "object",
"properties": {
"message": {"type": "string", "description": "Message to broadcast"}
},
"required": ["message"]
}
}
}
def broadcast_message(message: str) -> str:
# CoPaw handles routing; return the message and let the agent deliver it
return f"[BROADCAST] {message}"
```
### Pattern: File summarization skill
```python
# skills/summarize_file.py
SKILL_NAME = "summarize_file"
SKILL_DESCRIPTION = "Read and summarize a local file"
SKILL_SCHEMA = {
"type": "function",
"function": {
"name": SKILL_NAME,
"description": SKILL_DESCRIPTION,
"parameters": {
"type": "object",
"properties": {
"file_path": {"type": "string", "description": "Absolute path to the file"}
},
"required": ["file_path"]
}
}
}
def summarize_file(file_path: str) -> str:
import os
path = os.path.expanduser(file_path)
if not os.path.exists(path):
return f"File not found: {path}"
with open(path, "r", encoding="utf-8", errors="ignore") as f:
content = f.read(8000)
return f"File: {path}\nSize: {os.path.getsize(path)} bytes\nContent preview:\n{content}"
```
---
## Troubleshooting
### Console not accessible at port 8088
```bash
# Use a different port
copaw app --port 8090
# Check if another process is using 8088
lsof -i :8088 # macOS/Linux
netstat -ano | findstr :8088 # Windows
```
### Skills not loading
- Confirm the skill file is in `~/.copaw/workspace/skills/`
- Confirm `SKILL_NAME`, `SKILL_DESCRIPTION`, `SKILL_SCHEMA`, and the handler function are all defined at module level
- Check `~/.copaw/workspace/logs/` for import errors
- Restart `copaw app` after adding new skill files
### Channel not receiving messages
1. Verify credentials are set correctly (env vars or `config.yaml`)
2. Check the Console → Channels page for connection status
3. For DingTalk/Feishu/Discord with `mention_only: true`, the bot must be @mentioned
4. Discord messages over 2000 characters are split automatically — ensure the bot has `Send Messages` permission
### LLM provider connection fails
```bash
# Test provider from CLI (Console → Providers → Test Connection)
# Or check logs:
tail -f ~/.copaw/workspace/logs/copaw.log
```
- For Ollama: confirm `ollama serve` is running and `base_url` matches
- For OpenAI-compatible APIs: verify `base_url` ends with `/v1`
- LLM calls auto-retry with exponential backoff — transient failures resolve automatically
### Windows encoding issues
```cmd
# Set UTF-8 encoding for CMD
chcp 65001
```
Or set in environment:
```bash
export PYTHONIOENCODING=utf-8
```
### Workspace reset
```bash
# Reinitialize workspace (preserves skills/)
copaw init
# Full reset (destructive)
rm -rf ~/.copaw/workspace
copaw init --defaults
```
---
## ModelScope Cloud Deployment
For one-click cloud deployment without local setup:
1. Visit [ModelScope CoPaw Studio](https://modelscope.cn/studios/fork?target=AgentScope/CoPaw)
2. Fork the studio to your account
3. Set environment variables in the studio settings
4. Start the studio — Console is accessible via the studio URL
---
## Key Links
- **Documentation**: https://copaw.agentscope.io/
- **Channel setup guides**: https://copaw.agentscope.io/docs/channels
- **Release notes**: https://agentscope-ai.github.io/CoPaw/release-notes
- **GitHub**: https://github.com/agentscope-ai/CoPaw
- **PyPI**: https://pypi.org/project/copaw/
- **Discord community**: https://discord.gg/eYMpfnkG8hRelated Skills
picoclaw-ai-assistant
Ultra-lightweight AI assistant in Go that runs on $10 hardware with <10MB RAM, supporting multiple LLM providers, tools, and single-binary deployment across RISC-V, ARM, MIPS, and x86.
metatron-pentest-assistant
AI-powered penetration testing assistant using local LLM (metatron-qwen via Ollama) on Parrot OS Linux
gstack-workflow-assistant
Team of specialist AI workflows for Claude Code with CEO review, engineering planning, code review, shipping, QA testing, and browser automation
```markdown
---
zeroboot-vm-sandbox
Sub-millisecond VM sandboxes for AI agents using copy-on-write KVM forking via Zeroboot
yourvpndead-vpn-detection
Android app that detects VPN/proxy servers (VLESS/xray/sing-box) via local SOCKS5 vulnerability, exposing exit IPs and server configs without root
xata-postgres-platform
Expert skill for Xata open-source cloud-native Postgres platform with copy-on-write branching, scale-to-zero, and Kubernetes deployment
x-mentor-skill-nuwa
AI-powered X (Twitter) content strategy skill that distills methodologies from 6 top creators + open-source algorithm data into actionable writing, growth, and monetization guidance.
wx-favorites-report
End-to-end pipeline to extract, decrypt, and visualize WeChat Mac favorites from encrypted SQLite DB into an interactive HTML report.
wterm-web-terminal
Web terminal emulator with Zig/WASM core, DOM rendering, and React/vanilla JS bindings
worldmonitor-intelligence-dashboard
Real-time global intelligence dashboard with AI-powered news aggregation, geopolitical monitoring, and infrastructure tracking
witr-process-inspector
CLI and TUI tool that explains why processes, services, and ports are running by tracing causality chains across supervisors, containers, and shells.