17 KiB
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:
- 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.
- 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.
- Performance and binary size are product goals, not nice-to-have
Cargo.tomlrelease profile and dependency choices optimize for size and determinism.- Convenience dependencies and broad abstractions can silently regress these goals.
- Config and runtime contracts are user-facing API
src/config/schema.rsand CLI commands are effectively public interfaces.- Backward compatibility and explicit migration matter.
- 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 routingsrc/lib.rs— module exports and shared command enumssrc/config/— schema + config loading/mergingsrc/agent/— orchestration loopsrc/gateway/— webhook/gateway serversrc/security/— policy, pairing, secret storesrc/memory/— markdown/sqlite memory backends + embeddings/vector mergesrc/providers/— model providers and resilient wrappersrc/channels/— Telegram/Discord/Slack/etc channelssrc/tools/— tool execution surface (shell, file, memory, browser)src/peripherals/— hardware peripherals (STM32, RPi GPIO); seedocs/hardware-peripherals-design.mdsrc/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)
- Read before write
- Inspect existing module, factory wiring, and adjacent tests before editing.
- Define scope boundary
- One concern per PR; avoid mixed feature+refactor+infra patches.
- Implement minimal patch
- Apply KISS/YAGNI/DRY rule-of-three explicitly.
- Validate by risk tier
- Docs-only: lightweight checks.
- Code/risky changes: full relevant checks and focused scenarios.
- Document impact
- Update docs/PR notes for behavior, risk, side effects, and rollback.
- Respect queue hygiene
- If stacked PR: declare
Depends on #.... - If replacing old PR: declare
Supersedes #....
- If stacked PR: declare
6.3 Branch / Commit / PR Flow (Required)
All contributors (human or agent) must follow the same collaboration flow:
- Create and work from a non-
mainbranch. - Commit changes to that branch with clear, scoped commit messages.
- Open a PR to
main; do not push directly tomain. - 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/enumsPascalCase, functions/variablessnake_case, constants/staticsSCREAMING_SNAKE_CASE. - Name types and modules by domain role, not implementation detail (for example
DiscordChannel,SecurityPolicy,MemoryStoreover vague names likeManager/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 inchannels/, model I/O inproviders/, policy insecurity/, execution intools/. - 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
Providerinsrc/providers/. - Register in
src/providers/mod.rsfactory. - Add focused tests for factory wiring and error paths.
- Avoid provider-specific behavior leaks into shared orchestration code.
7.2 Adding a Channel
- Implement
Channelinsrc/channels/. - Keep
send,listen,health_check, typing semantics consistent. - Cover auth/allowlist/health behavior with tests.
7.3 Adding a Tool
- Implement
Toolinsrc/tools/with strict parameter schema. - Validate and sanitize all inputs.
- Return structured
ToolResult; avoid panics in runtime path.
5.4 Adding a Peripheral
- Implement
Peripheralinsrc/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.mdfor 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.
8) Validation Matrix
Default local checks for code changes:
cargo fmt --all -- --check
cargo clippy --all-targets -- -D warnings
cargo test
Preferred local pre-PR validation path (recommended, not required):
./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.mdfully (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
- actor labels:
- If reproducing external incidents, redact and anonymize all payloads before committing.
- Before push, review
git diff --cachedspecifically 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
\\ntext. - 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):
## 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>
Reference docs:
CONTRIBUTING.mddocs/pr-workflow.mddocs/reviewer-playbook.mddocs/ci-map.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:
- What changed
- What did not change
- Validation run and results
- Remaining risks / unknowns
- 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.