Files
flynn/docs/architecture/CONTRIBUTOR_MAP.md
T
2026-02-16 12:09:44 -08:00

251 lines
7.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 (Telegram/Discord/Slack/WhatsApp/Matrix/Signal/Mattermost/etc.)
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, _context?: { signal?: AbortSignal }): 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/
```