copaw-ai-assistant by aradotso/trending-skills
npx skills add https://github.com/aradotso/trending-skills --skill copaw-ai-assistant由 ara.so 提供的技能 — Daily 2026 技能集。
CoPaw 是一个可以部署在您自己的机器或云端的个人 AI 助手框架。它通过单一代理连接到多个聊天平台(钉钉、飞书、QQ、Discord、iMessage、Telegram、Mattermost、Matrix、MQTT),支持自定义 Python 技能、定时 cron 任务、本地和云端 LLM,并在 http://127.0.0.1:8088/ 提供一个网页控制台。
pip install copaw
copaw init --defaults # 使用合理的默认值进行非交互式设置
copaw app # 启动网页控制台 + 后端
macOS / Linux:
curl -fsSL https://copaw.agentscope.io/install.sh | bash
# 支持 Ollama:
curl -fsSL https://copaw.agentscope.io/install.sh | bash -s -- --extras ollama
# 多个额外功能:
curl -fsSL https://copaw.agentscope.io/install.sh | bash -s -- --extras ollama,llamacpp
Windows CMD:
curl -fsSL https://copaw.agentscope.io/install.bat -o install.bat && install.bat
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
Windows PowerShell:
irm https://copaw.agentscope.io/install.ps1 | iex
脚本安装后,打开一个新的终端:
copaw init --defaults
copaw app
git clone https://github.com/agentscope-ai/CoPaw.git
cd CoPaw
pip install -e ".[dev]"
copaw init --defaults
copaw app
copaw init # 交互式工作空间设置
copaw init --defaults # 非交互式设置
copaw app # 启动控制台 (http://127.0.0.1:8088/)
copaw app --port 8090 # 使用自定义端口
copaw --help # 列出所有命令
执行 copaw init 后,会创建一个工作空间(默认路径:~/.copaw/workspace/):
~/.copaw/workspace/
├── config.yaml # 代理、提供商、通道配置
├── skills/ # 自定义技能文件(自动加载)
│ └── my_skill.py
├── memory/ # 对话记忆存储
└── logs/ # 运行时日志
config.yaml)copaw init 会生成此文件。可以直接编辑它或使用控制台 UI。
providers:
- id: openai-main
type: openai
api_key: ${OPENAI_API_KEY} # 使用环境变量引用
model: gpt-4o
base_url: https://api.openai.com/v1
- id: local-ollama
type: ollama
model: llama3.2
base_url: http://localhost:11434
agent:
name: CoPaw
language: en # en, zh, ja 等
provider_id: openai-main
context_limit: 8000
channels:
- type: dingtalk
app_key: ${DINGTALK_APP_KEY}
app_secret: ${DINGTALK_APP_SECRET}
agent_id: ${DINGTALK_AGENT_ID}
mention_only: true # 仅在群聊中被@时响应
channels:
- type: feishu
app_id: ${FEISHU_APP_ID}
app_secret: ${FEISHU_APP_SECRET}
mention_only: false
channels:
- type: discord
token: ${DISCORD_BOT_TOKEN}
mention_only: true
channels:
- type: telegram
token: ${TELEGRAM_BOT_TOKEN}
channels:
- type: qq
uin: ${QQ_UIN}
password: ${QQ_PASSWORD}
channels:
- type: mattermost
url: ${MATTERMOST_URL}
token: ${MATTERMOST_TOKEN}
team: my-team
channels:
- type: matrix
homeserver: ${MATRIX_HOMESERVER}
user_id: ${MATRIX_USER_ID}
access_token: ${MATRIX_ACCESS_TOKEN}
技能是放置在 ~/.copaw/workspace/skills/ 目录下的 Python 文件。它们会在 CoPaw 启动时自动加载——无需注册步骤。
# ~/.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}"
# ~/.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}"
# ~/.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))
在 config.yaml 中定义 cron 任务,以便按计划运行技能并将结果推送到通道:
cron:
- id: daily-digest
schedule: "0 8 * * *" # 每天 08:00
skill: get_weather
skill_args:
city: "Tokyo"
channel_id: dingtalk-main # 匹配下面的通道 id
message_template: "Good morning! Today's weather: {result}"
- id: hourly-news
schedule: "0 * * * *"
skill: fetch_tech_news
channel_id: discord-main
# Install Ollama: https://ollama.ai
ollama pull llama3.2
ollama serve # starts on http://localhost:11434
# config.yaml
providers:
- id: ollama-local
type: ollama
model: llama3.2
base_url: http://localhost:11434
providers:
- id: lmstudio-local
type: lmstudio
model: lmstudio-community/Meta-Llama-3-8B-Instruct-GGUF
base_url: http://localhost:1234/v1
pip install "copaw[llamacpp]"
providers:
- id: llamacpp-local
type: llamacpp
model_path: /path/to/model.gguf
工具防护会拦截有风险的工具调用,并在执行前需要用户批准。在 config.yaml 中配置:
agent:
tool_guard:
enabled: true
risk_patterns:
- "rm -rf"
- "DROP TABLE"
- "os.system"
auto_approve_low_risk: true
当调用被拦截时,控制台会显示批准提示。用户可以在工具运行前批准或拒绝。
令牌使用量会自动追踪,并可在控制台仪表板中查看。也可以通过编程方式访问:
# 在技能或调试脚本中
from copaw.telemetry import get_usage_summary
summary = get_usage_summary()
print(summary)
# {'total_tokens': 142300, 'prompt_tokens': 98200, 'completion_tokens': 44100, 'by_provider': {...}}
在运行 copaw app 之前设置这些变量,或者在 config.yaml 中通过 ${VAR_NAME} 引用它们:
# LLM 提供商
export OPENAI_API_KEY=...
export ANTHROPIC_API_KEY=...
# 通道
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=...
# 自定义技能密钥
export OPENWEATHER_API_KEY=...
# config.yaml 节选
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" # 工作日 07:30
skill: daily_briefing
channel_id: dingtalk-main
# 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")
# 在此处添加您自己的数据源
return f"Good morning! Today is {today}. Have a productive day!"
# 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 处理路由;返回消息并让代理发送它
return f"[BROADCAST] {message}"
# 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}"
# 使用不同的端口
copaw app --port 8090
# 检查是否有其他进程占用了 8088 端口
lsof -i :8088 # macOS/Linux
netstat -ano | findstr :8088 # Windows
~/.copaw/workspace/skills/ 目录下SKILL_NAME、SKILL_DESCRIPTION、SKILL_SCHEMA 和处理函数都在模块级别定义~/.copaw/workspace/logs/ 中的导入错误copaw appconfig.yaml)mention_only: true 的钉钉/飞书/Discord,机器人必须被@提及发送消息 权限# 从 CLI 测试提供商(控制台 → 提供商 → 测试连接)
# 或检查日志:
tail -f ~/.copaw/workspace/logs/copaw.log
ollama serve 正在运行且 base_url 匹配base_url 以 /v1 结尾# 为 CMD 设置 UTF-8 编码
chcp 65001
或在环境中设置:
export PYTHONIOENCODING=utf-8
# 重新初始化工作空间(保留 skills/ 目录)
copaw init
# 完全重置(破坏性操作)
rm -rf ~/.copaw/workspace
copaw init --defaults
无需本地设置,一键云端部署:
每周安装量
325
仓库
GitHub 星标数
10
首次出现
7 天前
安全审计
安装于
gemini-cli321
github-copilot321
amp321
cline321
codex321
kimi-cli321
Skill by 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/.
pip install copaw
copaw init --defaults # non-interactive setup with sensible defaults
copaw app # starts the web Console + backend
macOS / Linux:
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:
curl -fsSL https://copaw.agentscope.io/install.bat -o install.bat && install.bat
Windows PowerShell:
irm https://copaw.agentscope.io/install.ps1 | iex
After script install, open a new terminal:
copaw init --defaults
copaw app
git clone https://github.com/agentscope-ai/CoPaw.git
cd CoPaw
pip install -e ".[dev]"
copaw init --defaults
copaw app
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
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
config.yaml)copaw init generates this file. Edit it directly or use the Console UI.
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:
name: CoPaw
language: en # en, zh, ja, etc.
provider_id: openai-main
context_limit: 8000
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
channels:
- type: feishu
app_id: ${FEISHU_APP_ID}
app_secret: ${FEISHU_APP_SECRET}
mention_only: false
channels:
- type: discord
token: ${DISCORD_BOT_TOKEN}
mention_only: true
channels:
- type: telegram
token: ${TELEGRAM_BOT_TOKEN}
channels:
- type: qq
uin: ${QQ_UIN}
password: ${QQ_PASSWORD}
channels:
- type: mattermost
url: ${MATTERMOST_URL}
token: ${MATTERMOST_TOKEN}
team: my-team
channels:
- type: matrix
homeserver: ${MATRIX_HOMESERVER}
user_id: ${MATRIX_USER_ID}
access_token: ${MATRIX_ACCESS_TOKEN}
Skills are Python files placed in ~/.copaw/workspace/skills/. They are auto-loaded when CoPaw starts — no registration step needed.
# ~/.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}"
# ~/.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}"
# ~/.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))
Define cron jobs in config.yaml to run skills on a schedule and push results to a channel:
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
# Install Ollama: https://ollama.ai
ollama pull llama3.2
ollama serve # starts on http://localhost:11434
# config.yaml
providers:
- id: ollama-local
type: ollama
model: llama3.2
base_url: http://localhost:11434
providers:
- id: lmstudio-local
type: lmstudio
model: lmstudio-community/Meta-Llama-3-8B-Instruct-GGUF
base_url: http://localhost:1234/v1
pip install "copaw[llamacpp]"
providers:
- id: llamacpp-local
type: llamacpp
model_path: /path/to/model.gguf
Tool Guard blocks risky tool calls and requires user approval before execution. Configure in config.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 is tracked automatically and visible in the Console dashboard. Access programmatically:
# 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': {...}}
Set these before running copaw app, or reference them in config.yaml as ${VAR_NAME}:
# 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=...
# 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
# 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!"
# 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}"
# 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}"
# 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
~/.copaw/workspace/skills/SKILL_NAME, SKILL_DESCRIPTION, SKILL_SCHEMA, and the handler function are all defined at module level~/.copaw/workspace/logs/ for import errorscopaw app after adding new skill filesconfig.yaml)mention_only: true, the bot must be @mentionedSend Messages permission# Test provider from CLI (Console → Providers → Test Connection)
# Or check logs:
tail -f ~/.copaw/workspace/logs/copaw.log
ollama serve is running and base_url matchesbase_url ends with /v1# Set UTF-8 encoding for CMD
chcp 65001
Or set in environment:
export PYTHONIOENCODING=utf-8
# Reinitialize workspace (preserves skills/)
copaw init
# Full reset (destructive)
rm -rf ~/.copaw/workspace
copaw init --defaults
For one-click cloud deployment without local setup:
Weekly Installs
325
Repository
GitHub Stars
10
First Seen
7 days ago
Security Audits
Gen Agent Trust HubFailSocketPassSnykWarn
Installed on
gemini-cli321
github-copilot321
amp321
cline321
codex321
kimi-cli321
AI Elements:基于shadcn/ui的AI原生应用组件库,快速构建对话界面
54,900 周安装
OpenAI Assistants API v2 使用指南与迁移方案 - 2026年弃用前必看
313 周安装
MCP CLI 脚本开发指南:为Claude Code构建高效本地工具与自动化脚本
313 周安装
Playwright MCP 开发指南:如何为微软 Playwright 添加 MCP 工具和 CLI 命令
313 周安装
Shopify开发专家 | 电商平台定制、API集成、主题开发与无头电商解决方案
313 周安装
Sentry SDK 设置指南:跨平台错误监控、性能追踪与会话回放集成
313 周安装
LLM安全指南:OWASP LLM十大安全风险2025防护规则与最佳实践
313 周安装