413 lines
18 KiB
Markdown
413 lines
18 KiB
Markdown
# AGENTS.md — ZeroClaw Agent Engineering Protocol
|
|
|
|
This file defines the default working protocol for coding agents in this repository.
|
|
Scope: entire repository.
|
|
|
|
## 1) Project Snapshot (Read First)
|
|
|
|
ZeroClaw is a Rust-first autonomous agent runtime optimized for:
|
|
|
|
- high performance
|
|
- high efficiency
|
|
- high stability
|
|
- high extensibility
|
|
- high sustainability
|
|
- high security
|
|
|
|
Core architecture is trait-driven and modular. Most extension work should be done by implementing traits and registering in factory modules.
|
|
|
|
Key extension points:
|
|
|
|
- `src/providers/traits.rs` (`Provider`)
|
|
- `src/channels/traits.rs` (`Channel`)
|
|
- `src/tools/traits.rs` (`Tool`)
|
|
- `src/memory/traits.rs` (`Memory`)
|
|
- `src/observability/traits.rs` (`Observer`)
|
|
- `src/runtime/traits.rs` (`RuntimeAdapter`)
|
|
- `src/peripherals/traits.rs` (`Peripheral`) — hardware boards (STM32, RPi GPIO)
|
|
|
|
## 2) Deep Architecture Observations (Why This Protocol Exists)
|
|
|
|
These codebase realities should drive every design decision:
|
|
|
|
1. **Trait + factory architecture is the stability backbone**
|
|
- Extension points are intentionally explicit and swappable.
|
|
- Most features should be added via trait implementation + factory registration, not cross-cutting rewrites.
|
|
2. **Security-critical surfaces are first-class and internet-adjacent**
|
|
- `src/gateway/`, `src/security/`, `src/tools/`, `src/runtime/` carry high blast radius.
|
|
- Defaults already lean secure-by-default (pairing, bind safety, limits, secret handling); keep it that way.
|
|
3. **Performance and binary size are product goals, not nice-to-have**
|
|
- `Cargo.toml` release profile and dependency choices optimize for size and determinism.
|
|
- Convenience dependencies and broad abstractions can silently regress these goals.
|
|
4. **Config and runtime contracts are user-facing API**
|
|
- `src/config/schema.rs` and CLI commands are effectively public interfaces.
|
|
- Backward compatibility and explicit migration matter.
|
|
5. **The project now runs in high-concurrency collaboration mode**
|
|
- CI + docs governance + label routing are part of the product delivery system.
|
|
- PR throughput is a design constraint; not just a maintainer inconvenience.
|
|
|
|
## 3) Engineering Principles (Normative)
|
|
|
|
These principles are mandatory by default. They are not slogans; they are implementation constraints.
|
|
|
|
### 3.1 KISS (Keep It Simple, Stupid)
|
|
|
|
**Why here:** Runtime + security behavior must stay auditable under pressure.
|
|
|
|
Required:
|
|
|
|
- Prefer straightforward control flow over clever meta-programming.
|
|
- Prefer explicit match branches and typed structs over hidden dynamic behavior.
|
|
- Keep error paths obvious and localized.
|
|
|
|
### 3.2 YAGNI (You Aren't Gonna Need It)
|
|
|
|
**Why here:** Premature features increase attack surface and maintenance burden.
|
|
|
|
Required:
|
|
|
|
- Do not add new config keys, trait methods, feature flags, or workflow branches without a concrete accepted use case.
|
|
- Do not introduce speculative “future-proof” abstractions without at least one current caller.
|
|
- Keep unsupported paths explicit (error out) rather than adding partial fake support.
|
|
|
|
### 3.3 DRY + Rule of Three
|
|
|
|
**Why here:** Naive DRY can create brittle shared abstractions across providers/channels/tools.
|
|
|
|
Required:
|
|
|
|
- Duplicate small, local logic when it preserves clarity.
|
|
- Extract shared utilities only after repeated, stable patterns (rule-of-three).
|
|
- When extracting, preserve module boundaries and avoid hidden coupling.
|
|
|
|
### 3.4 SRP + ISP (Single Responsibility + Interface Segregation)
|
|
|
|
**Why here:** Trait-driven architecture already encodes subsystem boundaries.
|
|
|
|
Required:
|
|
|
|
- Keep each module focused on one concern.
|
|
- Extend behavior by implementing existing narrow traits whenever possible.
|
|
- Avoid fat interfaces and “god modules” that mix policy + transport + storage.
|
|
|
|
### 3.5 Fail Fast + Explicit Errors
|
|
|
|
**Why here:** Silent fallback in agent runtimes can create unsafe or costly behavior.
|
|
|
|
Required:
|
|
|
|
- Prefer explicit `bail!`/errors for unsupported or unsafe states.
|
|
- Never silently broaden permissions/capabilities.
|
|
- Document fallback behavior when fallback is intentional and safe.
|
|
|
|
### 3.6 Secure by Default + Least Privilege
|
|
|
|
**Why here:** Gateway/tools/runtime can execute actions with real-world side effects.
|
|
|
|
Required:
|
|
|
|
- Deny-by-default for access and exposure boundaries.
|
|
- Never log secrets, raw tokens, or sensitive payloads.
|
|
- Keep network/filesystem/shell scope as narrow as possible unless explicitly justified.
|
|
|
|
### 3.7 Determinism + Reproducibility
|
|
|
|
**Why here:** Reliable CI and low-latency triage depend on deterministic behavior.
|
|
|
|
Required:
|
|
|
|
- Prefer reproducible commands and locked dependency behavior in CI-sensitive paths.
|
|
- Keep tests deterministic (no flaky timing/network dependence without guardrails).
|
|
- Ensure local validation commands map to CI expectations.
|
|
|
|
### 3.8 Reversibility + Rollback-First Thinking
|
|
|
|
**Why here:** Fast recovery is mandatory under high PR volume.
|
|
|
|
Required:
|
|
|
|
- Keep changes easy to revert (small scope, clear blast radius).
|
|
- For risky changes, define rollback path before merge.
|
|
- Avoid mixed mega-patches that block safe rollback.
|
|
|
|
## 4) Repository Map (High-Level)
|
|
|
|
- `src/main.rs` — CLI entrypoint and command routing
|
|
- `src/lib.rs` — module exports and shared command enums
|
|
- `src/config/` — schema + config loading/merging
|
|
- `src/agent/` — orchestration loop
|
|
- `src/gateway/` — webhook/gateway server
|
|
- `src/security/` — policy, pairing, secret store
|
|
- `src/memory/` — markdown/sqlite memory backends + embeddings/vector merge
|
|
- `src/providers/` — model providers and resilient wrapper
|
|
- `src/channels/` — Telegram/Discord/Slack/etc channels
|
|
- `src/tools/` — tool execution surface (shell, file, memory, browser)
|
|
- `src/peripherals/` — hardware peripherals (STM32, RPi GPIO); see `docs/hardware-peripherals-design.md`
|
|
- `src/runtime/` — runtime adapters (currently native)
|
|
- `docs/` — architecture + process docs
|
|
- `.github/` — CI, templates, automation workflows
|
|
|
|
## 5) Risk Tiers by Path (Review Depth Contract)
|
|
|
|
Use these tiers when deciding validation depth and review rigor.
|
|
|
|
- **Low risk**: docs/chore/tests-only changes
|
|
- **Medium risk**: most `src/**` behavior changes without boundary/security impact
|
|
- **High risk**: `src/security/**`, `src/runtime/**`, `src/gateway/**`, `src/tools/**`, `.github/workflows/**`, access-control boundaries
|
|
|
|
When uncertain, classify as higher risk.
|
|
|
|
## 6) Agent Workflow (Required)
|
|
|
|
1. **Read before write**
|
|
- Inspect existing module, factory wiring, and adjacent tests before editing.
|
|
2. **Define scope boundary**
|
|
- One concern per PR; avoid mixed feature+refactor+infra patches.
|
|
3. **Implement minimal patch**
|
|
- Apply KISS/YAGNI/DRY rule-of-three explicitly.
|
|
4. **Validate by risk tier**
|
|
- Docs-only: lightweight checks.
|
|
- Code/risky changes: full relevant checks and focused scenarios.
|
|
5. **Document impact**
|
|
- Update docs/PR notes for behavior, risk, side effects, and rollback.
|
|
6. **Respect queue hygiene**
|
|
- If stacked PR: declare `Depends on #...`.
|
|
- If replacing old PR: declare `Supersedes #...`.
|
|
|
|
### 6.3 Branch / Commit / PR Flow (Required)
|
|
|
|
All contributors (human or agent) must follow the same collaboration flow:
|
|
|
|
- Create and work from a non-`main` branch.
|
|
- Commit changes to that branch with clear, scoped commit messages.
|
|
- Open a PR to `main`; do not push directly to `main`.
|
|
- Wait for required checks and review outcomes before merging.
|
|
- Merge via PR controls (squash/rebase/merge as repository policy allows).
|
|
- Branch deletion after merge is optional; long-lived branches are allowed when intentionally maintained.
|
|
|
|
### 6.4 Worktree Workflow (Required for Multi-Track Agent Work)
|
|
|
|
Use Git worktrees to isolate concurrent agent/human tracks safely and predictably:
|
|
|
|
- Use one worktree per active branch/PR stream to avoid cross-task contamination.
|
|
- Keep each worktree on a single branch; do not mix unrelated edits in one worktree.
|
|
- Run validation commands inside the corresponding worktree before commit/PR.
|
|
- Name worktrees clearly by scope (for example: `wt/ci-hardening`, `wt/provider-fix`) and remove stale worktrees when no longer needed.
|
|
- PR checkpoint rules from section 6.3 still apply to worktree-based development.
|
|
|
|
### 6.1 Code Naming Contract (Required)
|
|
|
|
Apply these naming rules for all code changes unless a subsystem has a stronger existing pattern.
|
|
|
|
- Use Rust standard casing consistently: modules/files `snake_case`, types/traits/enums `PascalCase`, functions/variables `snake_case`, constants/statics `SCREAMING_SNAKE_CASE`.
|
|
- Name types and modules by domain role, not implementation detail (for example `DiscordChannel`, `SecurityPolicy`, `MemoryStore` over vague names like `Manager`/`Helper`).
|
|
- Keep trait implementer naming explicit and predictable: `<ProviderName>Provider`, `<ChannelName>Channel`, `<ToolName>Tool`, `<BackendName>Memory`.
|
|
- Keep factory registration keys stable, lowercase, and user-facing (for example `"openai"`, `"discord"`, `"shell"`), and avoid alias sprawl without migration need.
|
|
- Name tests by behavior/outcome (`<subject>_<expected_behavior>`) and keep fixture identifiers neutral/project-scoped.
|
|
- If identity-like naming is required in tests/examples, use ZeroClaw-native labels only (`ZeroClawAgent`, `zeroclaw_user`, `zeroclaw_node`).
|
|
|
|
### 6.2 Architecture Boundary Contract (Required)
|
|
|
|
Use these rules to keep the trait/factory architecture stable under growth.
|
|
|
|
- Extend capabilities by adding trait implementations + factory wiring first; avoid cross-module rewrites for isolated features.
|
|
- Keep dependency direction inward to contracts: concrete integrations depend on trait/config/util layers, not on other concrete integrations.
|
|
- Avoid creating cross-subsystem coupling (for example provider code importing channel internals, tool code mutating gateway policy directly).
|
|
- Keep module responsibilities single-purpose: orchestration in `agent/`, transport in `channels/`, model I/O in `providers/`, policy in `security/`, execution in `tools/`.
|
|
- Introduce new shared abstractions only after repeated use (rule-of-three), with at least one real caller in current scope.
|
|
- For config/schema changes, treat keys as public contract: document defaults, compatibility impact, and migration/rollback path.
|
|
|
|
## 7) Change Playbooks
|
|
|
|
### 7.1 Adding a Provider
|
|
|
|
- Implement `Provider` in `src/providers/`.
|
|
- Register in `src/providers/mod.rs` factory.
|
|
- Add focused tests for factory wiring and error paths.
|
|
- Avoid provider-specific behavior leaks into shared orchestration code.
|
|
|
|
### 7.2 Adding a Channel
|
|
|
|
- Implement `Channel` in `src/channels/`.
|
|
- Keep `send`, `listen`, `health_check`, typing semantics consistent.
|
|
- Cover auth/allowlist/health behavior with tests.
|
|
|
|
### 7.3 Adding a Tool
|
|
|
|
- Implement `Tool` in `src/tools/` with strict parameter schema.
|
|
- Validate and sanitize all inputs.
|
|
- Return structured `ToolResult`; avoid panics in runtime path.
|
|
|
|
### 5.4 Adding a Peripheral
|
|
|
|
- Implement `Peripheral` in `src/peripherals/`.
|
|
- Peripherals expose `tools()` — each tool delegates to the hardware (GPIO, sensors, etc.).
|
|
- Register board type in config schema if needed.
|
|
- See `docs/hardware-peripherals-design.md` for protocol and firmware notes.
|
|
|
|
### 5.5 Security / Runtime / Gateway Changes
|
|
|
|
- Include threat/risk notes and rollback strategy.
|
|
- Add/update tests or validation evidence for failure modes and boundaries.
|
|
- Keep observability useful but non-sensitive.
|
|
- For `.github/workflows/**` changes, include Actions allowlist impact in PR notes and update `docs/actions-source-policy.md` when sources change.
|
|
|
|
## 8) Validation Matrix
|
|
|
|
Default local checks for code changes:
|
|
|
|
```bash
|
|
cargo fmt --all -- --check
|
|
cargo clippy --all-targets -- -D warnings
|
|
cargo test
|
|
```
|
|
|
|
Preferred local pre-PR validation path (recommended, not required):
|
|
|
|
```bash
|
|
./dev/ci.sh all
|
|
```
|
|
|
|
Notes:
|
|
|
|
- Local Docker-based CI is strongly recommended when Docker is available.
|
|
- Contributors are not blocked from opening a PR if local Docker CI is unavailable; in that case run the most relevant native checks and document what was run.
|
|
|
|
Additional expectations by change type:
|
|
|
|
- **Docs/template-only**: run markdown lint and relevant doc checks.
|
|
- **Workflow changes**: validate YAML syntax; run workflow lint/sanity checks when available.
|
|
- **Security/runtime/gateway/tools**: include at least one boundary/failure-mode validation.
|
|
|
|
If full checks are impractical, run the most relevant subset and document what was skipped and why.
|
|
|
|
## 9) Collaboration and PR Discipline
|
|
|
|
- Follow `.github/pull_request_template.md` fully (including side effects / blast radius).
|
|
- Keep PR descriptions concrete: problem, change, non-goals, risk, rollback.
|
|
- Use conventional commit titles.
|
|
- Prefer small PRs (`size: XS/S/M`) when possible.
|
|
- Agent-assisted PRs are welcome, **but contributors remain accountable for understanding what their code will do**.
|
|
|
|
### 9.1 Privacy/Sensitive Data and Neutral Wording (Required)
|
|
|
|
Treat privacy and neutrality as merge gates, not best-effort guidelines.
|
|
|
|
- Never commit personal or sensitive data in code, docs, tests, fixtures, snapshots, logs, examples, or commit messages.
|
|
- Prohibited data includes (non-exhaustive): real names, personal emails, phone numbers, addresses, access tokens, API keys, credentials, IDs, and private URLs.
|
|
- Use neutral project-scoped placeholders (for example: `user_a`, `test_user`, `project_bot`, `example.com`) instead of real identity data.
|
|
- Test names/messages/fixtures must be impersonal and system-focused; avoid first-person or identity-specific language.
|
|
- If identity-like context is unavoidable, use ZeroClaw-scoped roles/labels only (for example: `ZeroClawAgent`, `ZeroClawOperator`, `zeroclaw_user`) and avoid real-world personas.
|
|
- Recommended identity-safe naming palette (use when identity-like context is required):
|
|
- actor labels: `ZeroClawAgent`, `ZeroClawOperator`, `ZeroClawMaintainer`, `zeroclaw_user`
|
|
- service/runtime labels: `zeroclaw_bot`, `zeroclaw_service`, `zeroclaw_runtime`, `zeroclaw_node`
|
|
- environment labels: `zeroclaw_project`, `zeroclaw_workspace`, `zeroclaw_channel`
|
|
- If reproducing external incidents, redact and anonymize all payloads before committing.
|
|
- Before push, review `git diff --cached` specifically for accidental sensitive strings and identity leakage.
|
|
|
|
### 9.2 Superseded-PR Attribution (Required)
|
|
|
|
When a PR supersedes another contributor's PR and carries forward substantive code or design decisions, preserve authorship explicitly.
|
|
|
|
- In the integrating commit message, add one `Co-authored-by: Name <email>` trailer per superseded contributor whose work is materially incorporated.
|
|
- Use a GitHub-recognized email (`<login@users.noreply.github.com>` or the contributor's verified commit email) so attribution is rendered correctly.
|
|
- Keep trailers on their own lines after a blank line at commit-message end; never encode them as escaped `\\n` text.
|
|
- In the PR body, list superseded PR links and briefly state what was incorporated from each.
|
|
- If no actual code/design was incorporated (only inspiration), do not use `Co-authored-by`; give credit in PR notes instead.
|
|
|
|
### 9.3 Superseded-PR PR Template (Recommended)
|
|
|
|
When superseding multiple PRs, use a consistent title/body structure to reduce reviewer ambiguity.
|
|
|
|
- Recommended title format: `feat(<scope>): unify and supersede #<pr_a>, #<pr_b> [and #<pr_n>]`
|
|
- If this is docs/chore/meta only, keep the same supersede suffix and use the appropriate conventional-commit type.
|
|
- In the PR body, include the following template (fill placeholders, remove non-applicable lines):
|
|
|
|
```md
|
|
## Supersedes
|
|
- #<pr_a> by @<author_a>
|
|
- #<pr_b> by @<author_b>
|
|
- #<pr_n> by @<author_n>
|
|
|
|
## Integrated Scope
|
|
- From #<pr_a>: <what was materially incorporated>
|
|
- From #<pr_b>: <what was materially incorporated>
|
|
- From #<pr_n>: <what was materially incorporated>
|
|
|
|
## Attribution
|
|
- Co-authored-by trailers added for materially incorporated contributors: Yes/No
|
|
- If No, explain why (for example: no direct code/design carry-over)
|
|
|
|
## Non-goals
|
|
- <explicitly list what was not carried over>
|
|
|
|
## Risk and Rollback
|
|
- Risk: <summary>
|
|
- Rollback: <revert commit/PR strategy>
|
|
```
|
|
|
|
### 9.4 Superseded-PR Commit Template (Recommended)
|
|
|
|
When a commit unifies or supersedes prior PR work, use a deterministic commit message layout so attribution is machine-parsed and reviewer-friendly.
|
|
|
|
- Keep one blank line between message sections, and exactly one blank line before trailer lines.
|
|
- Keep each trailer on its own line; do not wrap, indent, or encode as escaped `\n` text.
|
|
- Add one `Co-authored-by` trailer per materially incorporated contributor, using GitHub-recognized email.
|
|
- If no direct code/design is carried over, omit `Co-authored-by` and explain attribution in the PR body instead.
|
|
|
|
```text
|
|
feat(<scope>): unify and supersede #<pr_a>, #<pr_b> [and #<pr_n>]
|
|
|
|
<one-paragraph summary of integrated outcome>
|
|
|
|
Supersedes:
|
|
- #<pr_a> by @<author_a>
|
|
- #<pr_b> by @<author_b>
|
|
- #<pr_n> by @<author_n>
|
|
|
|
Integrated scope:
|
|
- <subsystem_or_feature_a>: from #<pr_x>
|
|
- <subsystem_or_feature_b>: from #<pr_y>
|
|
|
|
Co-authored-by: <Name A> <login_a@users.noreply.github.com>
|
|
Co-authored-by: <Name B> <login_b@users.noreply.github.com>
|
|
```
|
|
|
|
Reference docs:
|
|
|
|
- `CONTRIBUTING.md`
|
|
- `docs/pr-workflow.md`
|
|
- `docs/reviewer-playbook.md`
|
|
- `docs/ci-map.md`
|
|
- `docs/actions-source-policy.md`
|
|
|
|
## 10) Anti-Patterns (Do Not)
|
|
|
|
- Do not add heavy dependencies for minor convenience.
|
|
- Do not silently weaken security policy or access constraints.
|
|
- Do not add speculative config/feature flags “just in case”.
|
|
- Do not mix massive formatting-only changes with functional changes.
|
|
- Do not modify unrelated modules “while here”.
|
|
- Do not bypass failing checks without explicit explanation.
|
|
- Do not hide behavior-changing side effects in refactor commits.
|
|
- Do not include personal identity or sensitive information in test data, examples, docs, or commits.
|
|
|
|
## 11) Handoff Template (Agent -> Agent / Maintainer)
|
|
|
|
When handing off work, include:
|
|
|
|
1. What changed
|
|
2. What did not change
|
|
3. Validation run and results
|
|
4. Remaining risks / unknowns
|
|
5. Next recommended action
|
|
|
|
## 12) Vibe Coding Guardrails
|
|
|
|
When working in fast iterative mode:
|
|
|
|
- Keep each iteration reversible (small commits, clear rollback).
|
|
- Validate assumptions with code search before implementing.
|
|
- Prefer deterministic behavior over clever shortcuts.
|
|
- Do not “ship and hope” on security-sensitive paths.
|
|
- If uncertain, leave a concrete TODO with verification context, not a hidden guess.
|