Introduces a comprehensive agent management system and a new research interface within the cockpit. This includes backend API endpoints for CRUD operations on agents, a new agent lifecycle manager, and frontend components for managing agents, skills, and research workflows. - feat(backend): add REST API for agent lifecycle management (list, create, update, delete, import) - feat(backend): implement `pkg/agent/manager` for agent lifecycle control - feat(gateway): register agent API routes in the gateway - feat(frontend): add cockpit tabs for Agents, Skills, and Research - feat(frontend): implement AgentsPage and ResearchPage components - feat(frontend): add `use-agents` and `use-cockpit-skills` hooks - docs: add Agent Management API documentation and update project map - refactor(tools): update ToolSkill metadata handling and regex parsing
514 lines
14 KiB
Markdown
514 lines
14 KiB
Markdown
# Tools API Documentation
|
|
|
|
## Overview
|
|
|
|
PicoClaw's tools system provides a extensible way for the AI agent to interact with the host system, web, hardware, and external services. Tools are registered in a centralized `ToolRegistry` and can be exposed to LLM providers via JSON Schema definitions.
|
|
|
|
## Architecture
|
|
|
|
### Tool Interface
|
|
|
|
All tools implement the base `Tool` interface (`pkg/tools/registry.go`):
|
|
|
|
```go
|
|
type Tool interface {
|
|
Name() string
|
|
Description() string
|
|
Parameters() map[string]any // JSON Schema
|
|
Execute(ctx context.Context, args map[string]any) *ToolResult
|
|
}
|
|
```
|
|
|
|
Optional interfaces for enhanced behavior:
|
|
|
|
- **`AsyncExecutor`** - Tools that support async execution with callback
|
|
- **`mediaStoreAware`** - Tools that need access to media storage
|
|
- **`PromptMetadataProvider`** - Tools that provide prompt layer/slot metadata
|
|
|
|
### Tool Registry
|
|
|
|
The `ToolRegistry` (`pkg/tools/registry.go`) manages all tools:
|
|
|
|
- **Core Tools**: Registered with `Register(tool)` - always available, no TTL
|
|
- **Hidden Tools**: Registered with `RegisterHidden(tool)` - have TTL (Time To Live), can be promoted
|
|
- **Tool Definitions**: `GetDefinitions()` returns JSON Schema for LLM providers
|
|
- **Provider Format**: `ToProviderDefs()` converts to provider-specific format (OpenAI, Anthropic, etc.)
|
|
|
|
### Tool Execution Flow
|
|
|
|
1. Tool called by agent with arguments
|
|
2. Arguments validated against tool's JSON Schema
|
|
3. Channel/ChatID context injected into `ctx`
|
|
4. `Execute()` or `ExecuteAsync()` called
|
|
5. Result normalized and returned as `ToolResult`
|
|
6. Panics recovered to prevent agent crashes
|
|
|
|
## Available Tools
|
|
|
|
### Filesystem Tools
|
|
|
|
| Tool Name | Description | Category | Config Key |
|
|
|-----------|-------------|----------|------------|
|
|
| `read_file` | Read file content from workspace or allowed paths | filesystem | `read_file` |
|
|
| `write_file` | Create or overwrite files within workspace | filesystem | `write_file` |
|
|
| `list_dir` | Inspect directories and enumerate files | filesystem | `list_dir` |
|
|
| `edit_file` | Apply targeted edits to existing files | filesystem | `edit_file` |
|
|
| `append_file` | Append content to end of existing file | filesystem | `append_file` |
|
|
|
|
**Implementation**: `pkg/tools/fs/` package
|
|
- Path validation against workspace restrictions
|
|
- Symlink resolution to prevent escaping workspace
|
|
- Configurable allow/deny path patterns
|
|
- Max file size limit: 64KB (configurable via `MaxReadFileSize`)
|
|
|
|
**Expected Arguments** (example for `read_file`):
|
|
```json
|
|
{
|
|
"path": "/path/to/file.txt",
|
|
"workspace": "/workspace" // injected automatically
|
|
}
|
|
```
|
|
|
|
### Shell/Exec Tool
|
|
|
|
| Tool Name | Description | Category | Config Key |
|
|
|-----------|-------------|----------|------------|
|
|
| `exec` | Run shell commands in workspace sandbox | filesystem | `exec` |
|
|
|
|
**Implementation**: `pkg/tools/shell.go`
|
|
- **Security**: Deny patterns block dangerous commands:
|
|
- `rm -rf`, `dd`, `shutdown`, `reboot`, `chmod`, `chown`, `sudo`
|
|
- Command substitution: `$(...)`, backticks
|
|
- Pipe to shell: `\| sh`, `\| bash`
|
|
- **Session Management**: Persistent shell sessions via `SessionManager`
|
|
- **Timeout**: Configurable command timeout
|
|
- **Working Directory**: Restricted to workspace by default
|
|
|
|
**Expected Arguments**:
|
|
```json
|
|
{
|
|
"command": "ls -la",
|
|
"workdir": "/workspace", // optional
|
|
"timeout": 30 // seconds, optional
|
|
}
|
|
```
|
|
|
|
### Automation Tools
|
|
|
|
| Tool Name | Description | Category | Config Key |
|
|
|-----------|-------------|----------|------------|
|
|
| `cron` | Schedule one-time or recurring tasks | automation | `cron` |
|
|
|
|
**Implementation**: `pkg/tools/cron.go`
|
|
- Schedule reminders, shell commands, and jobs
|
|
- One-time or recurring (cron expression support)
|
|
|
|
**Expected Arguments**:
|
|
```json
|
|
{
|
|
"action": "add", // add, list, remove
|
|
"schedule": "0 9 * * *", // cron format or "in 5m"
|
|
"command": "echo 'reminder'", // optional
|
|
"message": "Daily reminder" // optional
|
|
}
|
|
```
|
|
|
|
### Web Tools
|
|
|
|
| Tool Name | Description | Category | Config Key |
|
|
|-----------|-------------|----------|------------|
|
|
| `web_search` | Search the web using configured providers | web | `web` |
|
|
| `web_fetch` | Fetch and summarize webpage contents | web | `web_fetch` |
|
|
|
|
**Web Search Providers** (configured in `tools.web`):
|
|
- **Sogou** - Chinese search engine
|
|
- **DuckDuckGo** - Privacy-focused search
|
|
- **Brave Search** - Independent search (requires API key)
|
|
- **Tavily** - AI-optimized search (requires API key)
|
|
- **Perplexity** - AI search engine (requires API key)
|
|
- **SearXNG** - Metasearch engine (self-hosted)
|
|
- **GLM Search** - Chinese AI search (requires API key)
|
|
- **Baidu Search** - Chinese search engine (requires API key)
|
|
|
|
**Web Search Expected Arguments**:
|
|
```json
|
|
{
|
|
"query": "latest AI news",
|
|
"max_results": 5, // optional, default varies by provider
|
|
"provider": "brave" // optional, uses default
|
|
}
|
|
```
|
|
|
|
**Web Fetch Expected Arguments**:
|
|
```json
|
|
{
|
|
"url": "https://example.com",
|
|
"max_chars": 10000 // optional
|
|
}
|
|
```
|
|
|
|
### Communication Tools
|
|
|
|
| Tool Name | Description | Category | Config Key |
|
|
|-----------|-------------|----------|------------|
|
|
| `message` | Send follow-up message to active chat | communication | `message` |
|
|
| `send_file` | Send file or media to active chat | communication | `send_file` |
|
|
|
|
**Implementation**: `pkg/tools/integration_facade.go` → `pkg/tools/integration/`
|
|
|
|
**Message Tool Expected Arguments**:
|
|
```json
|
|
{
|
|
"text": "Hello from the agent!",
|
|
"channel": "telegram", // injected from context
|
|
"chat_id": "123456" // injected from context
|
|
}
|
|
```
|
|
|
|
**Send File Expected Arguments**:
|
|
```json
|
|
{
|
|
"path": "/workspace/report.pdf",
|
|
"caption": "Here's your file" // optional
|
|
}
|
|
```
|
|
|
|
### Skills Tools
|
|
|
|
| Tool Name | Description | Category | Config Key |
|
|
|-----------|-------------|----------|------------|
|
|
| `find_skills` | Search external skill registries | skills | `find_skills` |
|
|
| `install_skill` | Install skill from registry | skills | `install_skill` |
|
|
|
|
**Dependencies**: Requires `skills` config to be enabled
|
|
|
|
**Find Skills Expected Arguments**:
|
|
```json
|
|
{
|
|
"query": "pdf",
|
|
"limit": 10 // optional
|
|
}
|
|
```
|
|
|
|
**Install Skill Expected Arguments**:
|
|
```json
|
|
{
|
|
"name": "pdf-tools",
|
|
"source": "registry-url" // optional
|
|
}
|
|
```
|
|
|
|
### Agent/Subagent Tools
|
|
|
|
| Tool Name | Description | Category | Config Key |
|
|
|-----------|-------------|----------|------------|
|
|
| `spawn` | Launch background subagent for delegated work | agents | `spawn` |
|
|
| `spawn_status` | Query status of spawned subagents | agents | `spawn_status` |
|
|
|
|
**Dependencies**: Requires `subagent` config to be enabled
|
|
|
|
**Spawn Tool Expected Arguments**:
|
|
```json
|
|
{
|
|
"task": "Research latest AI papers",
|
|
"model": "gpt-4", // optional
|
|
"max_tokens": 2000, // optional
|
|
"temperature": 0.7, // optional
|
|
"async": true // optional, run in background
|
|
}
|
|
```
|
|
|
|
**Spawn Status Expected Arguments**:
|
|
```json
|
|
{
|
|
"task_id": "abc123" // optional, returns specific task or all
|
|
}
|
|
```
|
|
|
|
### Hardware Tools
|
|
|
|
| Tool Name | Description | Category | Config Key | Platform |
|
|
|-----------|-------------|----------|------------|----------|
|
|
| `i2c` | Interact with I2C devices | hardware | `i2c` | Linux only |
|
|
| `spi` | Interact with SPI devices | hardware | `spi` | Linux only |
|
|
| `serial` | Interact with serial ports | hardware | `serial` | Linux/macOS/Windows |
|
|
|
|
**Implementation**: `pkg/tools/hardware_facade.go` → `pkg/tools/hardware/`
|
|
|
|
**I2C Expected Arguments**:
|
|
```json
|
|
{
|
|
"action": "read", // read, write
|
|
"bus": "/dev/i2c-1",
|
|
"address": 0x48,
|
|
"register": 0x00, // optional
|
|
"data": [0x01, 0x02] // for write
|
|
}
|
|
```
|
|
|
|
**Serial Expected Arguments**:
|
|
```json
|
|
{
|
|
"port": "/dev/ttyUSB0",
|
|
"baud": 9600,
|
|
"data": "hello" // string or bytes
|
|
}
|
|
```
|
|
|
|
### Discovery Tools (Hidden, TTL-based)
|
|
|
|
| Tool Name | Description | Category | Config Key |
|
|
|-----------|-------------|----------|------------|
|
|
| `tool_search_tool_regex` | Discover hidden MCP tools by regex | discovery | `mcp.discovery.use_regex` |
|
|
| `tool_search_tool_bm25` | Discover hidden MCP tools by semantics | discovery | `mcp.discovery.use_bm25` |
|
|
| `request_permission` | Request user permission for outside-workspace access | permission | `exec.ask_permission` |
|
|
|
|
**Dependencies**: Requires `mcp` and `mcp.discovery` to be enabled
|
|
|
|
### Permission Tools
|
|
|
|
| Tool Name | Description | Category | Config Key |
|
|
|-----------|-------------|----------|------------|
|
|
| `request_permission` | Request user permission for outside-workspace access | permission | `exec.ask_permission` |
|
|
|
|
## Backend API Endpoints
|
|
|
|
### Base URL
|
|
```
|
|
http://localhost:<port>/api
|
|
```
|
|
|
|
### Tool Management
|
|
|
|
#### List All Tools
|
|
```
|
|
GET /api/tools
|
|
```
|
|
|
|
**Response**:
|
|
```json
|
|
{
|
|
"tools": [
|
|
{
|
|
"name": "read_file",
|
|
"description": "Read file content from the workspace",
|
|
"category": "filesystem",
|
|
"config_key": "read_file",
|
|
"status": "enabled", // enabled, disabled, blocked
|
|
"reason_code": "" // e.g., "requires_skills"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
#### Enable/Disable Tool
|
|
```
|
|
PUT /api/tools/{name}/state
|
|
```
|
|
|
|
**Request Body**:
|
|
```json
|
|
{
|
|
"enabled": true
|
|
}
|
|
```
|
|
|
|
**Response**:
|
|
```json
|
|
{
|
|
"status": "ok"
|
|
}
|
|
```
|
|
|
|
### Web Search Configuration
|
|
|
|
#### Get Web Search Config
|
|
```
|
|
GET /api/tools/web-search-config
|
|
```
|
|
|
|
**Response**:
|
|
```json
|
|
{
|
|
"provider": "auto", // auto, sogou, duckduckgo, brave, tavily, etc.
|
|
"current_service": "brave",
|
|
"prefer_native": false,
|
|
"proxy": "",
|
|
"providers": [
|
|
{
|
|
"id": "brave",
|
|
"label": "Brave Search",
|
|
"configured": true,
|
|
"current": true,
|
|
"requires_auth": true
|
|
}
|
|
],
|
|
"settings": {
|
|
"brave": {
|
|
"enabled": true,
|
|
"max_results": 10,
|
|
"api_key_set": true
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Update Web Search Config
|
|
```
|
|
PUT /api/tools/web-search-config
|
|
```
|
|
|
|
**Request Body**:
|
|
```json
|
|
{
|
|
"provider": "brave",
|
|
"prefer_native": false,
|
|
"proxy": "",
|
|
"settings": {
|
|
"brave": {
|
|
"enabled": true,
|
|
"max_results": 10,
|
|
"api_key": "BSA...", // or "api_keys": ["key1", "key2"]
|
|
"base_url": "" // optional for self-hosted
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
## Tool Result Structure
|
|
|
|
Tools return `*ToolResult` with the following fields:
|
|
|
|
```go
|
|
type ToolResult struct {
|
|
ForLLM string // Text returned to LLM for processing
|
|
ForUser string // Text shown to end user in chat
|
|
MediaURLs []string // Media attachment URLs (media:// or http://)
|
|
IsError bool // Whether execution failed
|
|
Async bool // True if running asynchronously
|
|
Err error // Underlying Go error (not serialized to JSON)
|
|
}
|
|
```
|
|
|
|
## MCP (Model Context Protocol) Integration
|
|
|
|
PicoClaw exposes tools via MCP server (`pkg/mcp/manager.go`):
|
|
|
|
- External MCP servers can be integrated
|
|
- Tools from MCP servers appear as hidden tools with TTL
|
|
- Discovery tools (`tool_search_tool_regex`, `tool_search_tool_bm25`) make hidden tools available
|
|
- MCP manager handles tool execution via isolated command transport
|
|
|
|
**MCP Tool Discovery Flow**:
|
|
1. MCP server registered with PicoClaw
|
|
2. Tools exposed as hidden (TTL=0, not visible to LLM)
|
|
3. Agent uses `tool_search_tool_regex` or `tool_search_tool_bm25`
|
|
4. Matching tools promoted (TTL set >0)
|
|
5. Promoted tools appear in next LLM context
|
|
|
|
## Configuration
|
|
|
|
Tools configured in `config.json` under `tools` section:
|
|
|
|
```json
|
|
{
|
|
"tools": {
|
|
"read_file": {"enabled": true},
|
|
"write_file": {"enabled": true},
|
|
"exec": {"enabled": true},
|
|
"web": {
|
|
"enabled": true,
|
|
"provider": "brave",
|
|
"brave": {
|
|
"enabled": true,
|
|
"max_results": 10,
|
|
"api_keys": ["BSA..."]
|
|
}
|
|
},
|
|
"mcp": {
|
|
"enabled": true,
|
|
"discovery": {
|
|
"enabled": true,
|
|
"use_regex": true,
|
|
"use_bm25": false
|
|
}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
## Security Considerations
|
|
|
|
1. **Path Restrictions**: Filesystem tools restrict access to workspace by default
|
|
2. **Shell Command Filtering**: Dangerous commands blocked via regex patterns
|
|
3. **Tool TTL**: Hidden tools auto-expire to prevent context bloat
|
|
4. **Media Store**: File paths converted to `media://` URLs for safe transport
|
|
5. **Panic Recovery**: Tool panics recovered to prevent agent crashes
|
|
6. **Symlink Resolution**: Prevents escaping workspace via symlinks
|
|
|
|
## Tool Registration Example
|
|
|
|
```go
|
|
// Register a core tool (always available)
|
|
registry.Register(tools.NewReadFileTool(workspace, true, 64*1024))
|
|
|
|
// Register a hidden tool (TTL-based)
|
|
registry.RegisterHidden(tools.NewRegexSearchTool(registry, 5, 10))
|
|
|
|
// Promote hidden tools (make them available to LLM)
|
|
registry.PromoteTools([]string{"tool_search_tool_regex"}, 10) // TTL=10 turns
|
|
```
|
|
|
|
## Agent Management API
|
|
|
|
PicoClaw provides REST API endpoints for managing custom agents in the cockpit. Agents are stored as Markdown files with YAML frontmatter in `~/.picoclaw/workspace/agents/`.
|
|
|
|
### Endpoints
|
|
|
|
| Method | Endpoint | Description |
|
|
|--------|----------|-------------|
|
|
| GET | `/api/agents` | List all agents |
|
|
| GET | `/api/agent?slug={slug}` | Get agent by slug |
|
|
| POST | `/api/agent/create` | Create new agent |
|
|
| PUT | `/api/agent/update?slug={slug}` | Update agent |
|
|
| DELETE | `/api/agent/delete?slug={slug}` | Delete agent |
|
|
| POST | `/api/agent/import` | Import agent from Markdown content |
|
|
|
|
### Data Types
|
|
|
|
```typescript
|
|
interface Agent {
|
|
slug: string
|
|
name: string
|
|
description: string
|
|
system_prompt: string
|
|
model: string
|
|
tool_permissions: string[]
|
|
status: "enabled" | "disabled"
|
|
created_at: string
|
|
updated_at: string
|
|
}
|
|
|
|
interface AgentCreateRequest {
|
|
name: string
|
|
description?: string
|
|
system_prompt: string
|
|
model: string
|
|
tool_permissions?: string[]
|
|
}
|
|
```
|
|
|
|
### Agent File Format
|
|
|
|
Agents are stored as `.md` files with YAML frontmatter:
|
|
|
|
```markdown
|
|
---
|
|
name: researcher
|
|
description: Research assistant agent
|
|
model: claude-3-5-sonnet
|
|
slug: researcher
|
|
---
|
|
|
|
You are a research assistant specialized in finding and summarizing information...
|
|
```
|