docs: add safety docs and OpenClaw gap roadmap

This commit is contained in:
William Valentin
2026-02-15 10:17:07 -08:00
parent 28304ac397
commit f2cdd1abd2
14 changed files with 3869 additions and 40 deletions
+250
View File
@@ -0,0 +1,250 @@
# Contributor Map (Agent-Oriented)
This is a fast navigation guide for contributors (human or AI). It answers:
- Where do I add a new tool?
- Where do I add a new skill?
- Where do I change routing/policy?
- What tests should I run?
For the execution-flow diagram, see `docs/architecture/AGENT_DIAGRAM.md`.
## 30-Second Repo Tour
```text
src/
daemon/ Start-up wiring, service init, message routing
backends/ Native agent + orchestrator (tool loop lives here)
tools/ Tool interfaces, policy, executor, builtins
skills/ Skill loader/registry + install/watch infra
hooks/ Confirm/log/silent policy + autonomy resolution
sandbox/ Docker sandbox manager + sandboxed tool wrappers
models/ Provider clients + model router + retry/cost/capabilities
channels/ Chat adapters + pairing gate
gateway/ WebSocket JSON-RPC server + web UI + handlers
memory/ Hybrid search + embeddings + persistence
session/ SQLite store + session mgmt
cli/ CLI entrypoints + setup wizard
automation/ Cron/webhooks/heartbeat/gmail watcher
docs/
api/ Tool and gateway protocol docs
security/ Capability model, sandboxing, injection resistance
architecture/ Diagrams + contributor maps
config/
default.yaml Example configuration
```
## Adding a New Tool
### Where code goes
- Builtins live in `src/tools/builtin/`.
- Core types live in `src/tools/types.ts`.
- Tools are registered through the daemon wiring (see existing patterns in `src/daemon/index.ts`).
### Minimal tool skeleton
```ts
import type { Tool, ToolResult } from '../types.js';
export const myTool: Tool = {
name: 'my.tool',
description: 'What it does (model-facing).',
// Optional: gate credentialed actions
requiredSecretScopes: ['my_scope'],
inputSchema: {
type: 'object',
properties: {
foo: { type: 'string', description: '...' },
},
required: ['foo'],
},
execute: async (rawArgs: unknown): Promise<ToolResult> => {
// ...
return { success: true, output: 'ok' };
},
};
```
### Security checklist
- If the tool calls an external service or uses credentials:
- set `requiredSecretScopes` on the tool.
- ensure skill permissions can gate it (`manifest.json.permissions.secrets`).
- If it reads/writes files:
- use `file.*` tools rather than bespoke FS access.
- skills can restrict FS paths via `permissions.fs`.
### Tests to add
- Unit tests in `src/tools/builtin/<tool>.test.ts`.
- If you touch policy/executor logic: add tests in `src/tools/policy.test.ts` or `src/tools/executor.test.ts`.
## Adding a New Skill
### What a skill is
A skill is a package with:
- `SKILL.md`: instructions injected into the system prompt.
- `manifest.json`: metadata + capability declarations.
Where skills live:
- Bundled skills: `skills/`
- Managed skills (installed by Flynn): configured skill directory (see config)
Skill loading:
- Loader: `src/skills/loader.ts`
- Registry: `src/skills/registry.ts`
- Watcher (optional): `src/skills/watcher.ts`
### Capability permissions
If the skill is used via routing (intent target type `skill`), add `permissions` to `manifest.json`.
Without `permissions`, a skill is still loadable, but in skill context it has no tool access.
Reference: `docs/security/SAFE_PERSONAL_AGENT.md`.
## Routing: Agents vs Skills vs Default
Where routing decisions happen:
- Inbound routing: `src/daemon/routing.ts`
Inputs to routing:
- Channel + sender (agent router)
- Intent registry (regex rules) — can target `agent` or `skill`
- Metadata overrides (gateway / channel adapters)
If you need a new routing rule type:
- Intent targets live in the intent registry/types (see `src/intents/registry.ts`).
## Tool Policy + Execution
You will usually touch these files for capability/security work:
- Tool allowlisting: `src/tools/policy.ts`
- Tool runtime enforcement + audit: `src/tools/executor.ts`
- Confirmation/autonomy: `src/hooks/engine.ts`, `src/hooks/autonomy.ts`
In skill context:
- `ToolPolicyContext.skillName` and `.skillPermissions` are set in `src/daemon/routing.ts`.
- ToolPolicy filters available tools.
- ToolExecutor enforces fs/net/secret/injection restrictions even if a tool is somehow called.
## Sandbox
Sandbox components:
- Docker sandbox manager: `src/sandbox/manager.ts`
- Docker implementation: `src/sandbox/docker.ts`
- Sandboxed tool wrappers: `src/sandbox/tools.ts`
- Tool replacement wiring: `src/daemon/routing.ts`
Notes:
- Today the sandbox wiring replaces `shell.exec` and `process.start` when sandbox is enabled.
- In skill context, high-risk execution defaults to sandbox unless the skill opts into host execution.
## Gateway / API Surface
Gateway protocol docs:
- `docs/api/PROTOCOL.md`
Gateway handlers:
- `src/gateway/handlers/` (JSON-RPC methods)
Useful places to start:
- `src/gateway/server.ts` (server lifecycle)
- `src/gateway/protocol.ts` (types)
## Tests + Commands
Common checks:
```bash
pnpm typecheck
pnpm lint
pnpm test:run
```
Targeted tests for safety boundary changes:
- Tool policy: `pnpm test:run src/tools/policy.test.ts`
- Tool executor: `pnpm test:run src/tools/executor.test.ts`
- Skill loader: `pnpm test:run src/skills/loader.test.ts`
- Routing: `pnpm test:run src/daemon/routing.test.ts`
## First 3 PRs to Pick Up (Good Agent On-Ramps)
These are small, high-leverage changes that teach you the architecture quickly.
### PR 1: Add a new "narrow" skill + permissions
Goal: add a skill that can only do one bounded thing (example: summarize a URL).
Deliverables:
- `skills/url-summarizer/SKILL.md`
- `skills/url-summarizer/manifest.json` with permissions:
- `tool_groups: ["group:web"]`
- `net: [{"host":"*","ports":[443]}]` (or narrower if you prefer)
- `execution_environment: "sandbox"` (default)
Acceptance:
- Skill loads (`flynn doctor` / skills list)
- In skill context, `shell.exec` is not available
- `web.fetch` works for https URLs
### PR 2: Route into the skill via intents
Goal: make it easy to invoke the skill without special UI.
Deliverables:
- Add an `intents.rules[]` entry targeting `type: skill`
- Patterns like: `summarize *`, `tldr *`
Acceptance:
- A message like `summarize https://example.com` routes to the skill
- Tool list is capability-filtered for that skill context
### PR 3: Add an end-to-end safety test
Goal: lock in behavior so future refactors dont weaken the boundary.
Deliverables:
- A test that asserts: when routed to a skill context with web-only permissions:
- `ToolPolicy` excludes `shell.exec` and `file.write`
- `ToolExecutor` denies a direct attempt to call `file.write` outside allowed fs globs
Suggested test locations:
- `src/tools/policy.test.ts`
- `src/tools/executor.test.ts`
## Where to Add What (Cheat Sheet)
```text
New tool .................. src/tools/builtin/ + register in daemon
Tool allow/deny logic ...... src/tools/policy.ts
Tool runtime enforcement .... src/tools/executor.ts
New skill .................. skills/<name>/{SKILL.md,manifest.json}
Skill loader/validation ..... src/skills/loader.ts
Skill routing (intents) ..... src/daemon/routing.ts + config intents
Sandbox behavior ........... src/sandbox/* + src/daemon/routing.ts
Confirmation UX ............ src/hooks/* + frontends/gateway
Web UI changes ............. src/gateway/ui/
```