agent-mail
Use Agent Mail as an optional messaging and file-reservation adapter for explicitly coordinated writers. Triggers: "coordinate writers", "reserve files".
Install
npx skills add https://github.com/boshu2/agentops/tree/main/images/gemini/skills/agent-mail
claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install boshu2-agentops@llmmart
git clone https://github.com/boshu2/agentops.git
The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole boshu2/agentops collection as a plugin from our marketplace. Git is the plain clone.
Skill manifest
Agent Mail — optional coordination adapter
Agent Mail carries messages, acknowledgements, identities, and temporary file reservations. It is not a task tracker, queue, proof ledger, or lifecycle controller.
Reservations are advisory: they prevent collisions only because every cooperating writer checks them against the same absolute project path, and one writer registered against a different path resolution makes the whole ledger advisory fiction. Agent Mail enforces nothing on a writer that does not check.
Named failure mode — silence-as-status: reading an unanswered thread as "work stalled" or "work done"; mail silence proves only that no mail arrived.
Anti-pattern: widening or renewing a reservation unprompted when a conflict appears. Corrective: report the conflict to the caller as-is; scope and TTL changes are the caller's call.
Boundary
- Skip Agent Mail for a single writer.
- The caller supplies the absolute project path, agent identities, thread id, participants, paths, exclusivity, reason, and TTL.
- Reservations prevent accidental overlap among cooperating writers. They do not create work ownership or affect Plan, Candidate, or verdict semantics.
- Mail silence proves nothing about work status.
- A message or acknowledgement is evidence that communication occurred, not evidence that a change is correct or complete. The adapter cannot select AgentOps semantics, issue a binding verdict, or turn factory completion into delivery or validation proof.
- Release a reservation, including any
force_release, only on the caller's explicit request for that exact reservation. Force-release has no autonomous trigger; a conflict is reported, not force-cleared. - Agent Mail never selects work, changes tracker state, commits code, validates, integrates, closes, releases, or delivers work.
Modes and authority
Two disjoint surfaces; do not reach the second from the first:
- Coordination mode (default). Register identity, reserve/release the caller's paths, send/read/acknowledge the caller's threads. This is the whole of routine use, and all of it writes durable Agent Mail records.
- Admin / disaster-recovery mode (explicitly caller-authorized only).
Installing the git pre-commit guard,
doctor repair, backup/restore, and the irreversibleclear-and-reset-everythingare a separate mode. Each requires the caller's explicit authorization for that specific operation; none is ever performed as a side effect of coordination.clear-and-reset-everythingdeletes the database and all storage and cannot be undone — never run it, even with--force, without an explicit destructive-reset authorization from the caller.
Surfaces
Choose exactly one mailbox owner and access mode for each storage root. When an
HTTP/MCP daemon owns the root, use its MCP tools; do not point the direct am
CLI at the same database. Use the CLI fallback only with a root not owned by a
running Agent Mail runtime. A busy mailbox activity lock or a bounded read
timeout is a degraded adapter result, not permission to restart the service,
repair the database, or silently switch roots.
Use the MCP tools when they are present. Otherwise use the self-describing am
CLI. Pin the intended storage root explicitly, and discover current syntax with
am mail --help, am file_reservations --help, and related group help; do not
infer commands from remembered aliases. If a direct macOS read rejects a
symlinked snapshot directory such as /var, use a caller-scoped, non-symlinked
temporary directory for that isolated invocation or report the adapter
degraded; never weaken the traversal check.
One-shot use
- Confirm that multiple explicitly coordinated writers share the repository.
- Freeze one storage root and either MCP/server mode or direct-CLI mode; never mix both against the same live database.
- Register the caller-supplied identity against the same absolute project path.
- Reserve only the supplied paths, with a bounded TTL.
- Report conflicts without waiting, narrowing scope, or changing the plan.
- Send the supplied message once and record its id.
- Read or acknowledge only the requested thread.
- Before the caller advances a declared transition, verify every acknowledgement-required message in that transition has the intended recipient acknowledgement. Later traffic is not an implicit acknowledgement.
- Release only reservations the caller explicitly asks to release.
Output
Return the project, identity, thread/message ids, reservation ids and paths (with their TTLs), conflicts, and timestamps. The caller owns all subsequent decisions.
Terminal outcomes are explicit, never silent:
- Adapter unavailable — neither the MCP tools nor the
amCLI is present: report that Agent Mail is unavailable and stop. Do not fall back to hand-written coordination or treat the absence as "no conflicts". - Reservation conflict — report the conflicting reservation as-is; do not narrow, widen, renew, or force-release it.
- Mailbox ownership conflict — a daemon and direct CLI contend for one storage root: report the lock owner/mode and stop; do not restart, repair, or bypass the lock as a coordination side effect.
- Required acknowledgement pending — report the exact message and intended recipient and stop the dependent transition. Do not infer acknowledgement from a later reply or repair it after validation.
- Timeout / degraded surface — report the operation as timed out or degraded with what was and was not observed; a timeout is evidence, not "done".
- Cleanup — reservations released this session are listed by id; any left in place (still holding a TTL) are named so the caller can see what remains.
References
Files (agentops)
-
references
-
RECOVERY.md 5.2 KB
# Doctor & Disaster Recovery Diagnostics, repair, backup, and restore for Agent Mail. --- ## Quick Health Check ```bash am robot health # primary — CLI/direct, works without the HTTP server curl http://127.0.0.1:8765/health # only if the HTTP MCP server is running (am serve-http) # → {"status": "healthy"} ``` --- ## Doctor Commands ### Run Diagnostics ```bash # Basic check am doctor check # Verbose with details am doctor check --verbose # JSON output for automation am doctor check --json # Check specific project am doctor check /abs/path/project ``` **Checks performed:** - Stale file reservations (expired TTL) - Database integrity - Orphaned records - FTS index sync - Git archive consistency ### Preview Repairs (Dry Run) ```bash am doctor repair --dry-run ``` Shows what would be fixed without making changes. ### Apply Repairs ```bash # Interactive (prompts for confirmation) am doctor repair # Auto-confirm (creates backup first) am doctor repair --yes # With custom backup directory am doctor repair --yes --backup-dir /tmp/backups ``` --- ## Backup & Restore ### Create Backup ```bash # With label am archive save --label nightly # Default label (timestamp) am archive save ``` ### List Backups ```bash am doctor backups # JSON format am doctor backups --json ``` ### Restore from Backup ```bash # Preview what would be restored am doctor restore /path/to/backup.zip --dry-run # Perform restore am doctor restore /path/to/backup.zip --yes ``` --- ## Static Mailbox Export Export mailbox for auditors, stakeholders, or archives. ### Interactive Wizard (Recommended) ```bash am share wizard ``` Guides you through export options, signing, encryption, and deployment. ### Manual Export ```bash # Basic export am share export --output ./bundle # With cryptographic signing am share export \ --output ./bundle \ --signing-key ./keys/signing.key # With age encryption am share export \ --output ./bundle \ --age-recipient age1abc...xyz # Scrub sensitive content am share export \ --output ./bundle \ --scrub-preset strict # or 'standard' ``` ### Preview Exported Bundle ```bash am share preview ./bundle --port 9000 --open-browser ``` ### Verify Bundle Integrity ```bash am share verify ./bundle ``` ### Refresh Existing Bundle ```bash am share update ./bundle ``` ### Decrypt Age-Encrypted Bundle ```bash am share decrypt bundle.zip.age --identity ~/.age/key.txt ``` --- ## Dangerous Operations (admin/DR mode — explicit caller authorization required) These are the admin/disaster-recovery surface, not coordination. Each needs the caller's explicit authorization for that specific operation; none runs as a side effect of coordination. `doctor repair`, backup/restore, and especially the full reset below cross from advisory into destructive. ### Full Reset (Destructive, irreversible!) ```bash # Prompts for archive first — run only with explicit destructive-reset authorization am clear-and-reset-everything # Skips prompts — NEVER run without an explicit destructive-reset authorization am clear-and-reset-everything --force --no-archive ``` **WARNING:** Deletes the SQLite database and all storage contents and cannot be undone. `--force --no-archive` also skips the safety archive. Do not run either form on your own initiative; report the situation and let the caller authorize. --- ## File Reservation Management ### List Reservations ```bash # All reservations am file_reservations list /abs/path/project # Active only am file_reservations list /abs/path/project --active-only # Active with limit am file_reservations active /abs/path/project --limit 10 ``` ### Expiring Soon ```bash # Reservations expiring within 30 minutes am file_reservations soon /abs/path/project --minutes 30 ``` --- ## ACK Management ### Pending Acknowledgments ```bash am acks pending /abs/path/project GreenCastle --limit 10 ``` ### Overdue ACKs ```bash am acks overdue /abs/path/project GreenCastle --ttl-minutes 60 ``` ### Remind About Old ACKs ```bash am acks remind /abs/path/project GreenCastle --min-age-minutes 30 ``` --- ## Common Issues | Symptom | Diagnosis | Fix | |---------|-----------|-----| | Stale reservations accumulating | Agent crashed without releasing | `doctor repair --yes` | | FTS search returns wrong results | Index out of sync | `doctor repair --yes` | | "database is locked" | Another runtime may own or be actively using the selected storage root | Identify the owner and use that root's frozen access mode; report degraded if it remains busy, and do not restart the server as a coordination side effect | | "mailbox activity lock is busy" | A daemon or another direct runtime owns the same storage root | Use the running daemon through MCP, or a separately authorized isolated CLI root; do not restart or repair as a coordination side effect | | "refusing to traverse symlinked snapshot directory /var" on macOS | Direct-read snapshot temporary path resolves through macOS's `/var` symlink | For an isolated invocation, set `TMPDIR` to a non-symlinked caller-scoped temporary root; do not disable traversal protection | | Corrupted git archive | Interrupted write | Restore from backup | | Server won't start | Port conflict | `config set-port 9000` | -
TOOLS.md 6.6 KB
# Agent Mail Tools Reference ## Table of Contents - [Project & Identity](#project--identity) - [Messaging](#messaging) - [File Reservations](#file-reservations) - [Contact Management](#contact-management) - [Macros](#macros) - [Guard Tools](#guard-tools) - [Health](#health) --- ## Project & Identity ### ensure_project Create/ensure project exists. ``` ensure_project(human_key="/abs/path/to/project") ``` **Returns:** `{id, slug, human_key, created_at}` ### register_agent Register identity in project. ``` register_agent( project_key="/abs/path/project", program="codex-cli", model="YOUR_MODEL", name="GreenCastle", # Optional, auto-generates if omitted task_description="Auth work" ) ``` **Agent naming rules:** - MUST be adjective+noun: GreenCastle, BlueLake, RedBear - NOT descriptive: BackendHarmonizer, DatabaseMigrator (invalid) - Best practice: Omit `name` for auto-generation **Returns:** `{id, name, program, model, task_description, inception_ts, last_active_ts}` ### whois Get agent profile with recent commits. ``` whois( project_key="/abs/path/project", agent_name="GreenCastle", include_recent_commits=true, commit_limit=5 ) ``` ### create_agent_identity Always create new unique agent (never updates existing). ``` create_agent_identity( project_key="/abs/path/project", program="codex-cli", model="YOUR_MODEL", name_hint="GreenCastle" # Optional ) ``` --- ## Messaging ### send_message Send message to one or more recipients. ``` send_message( project_key="/abs/path/project", sender_name="GreenCastle", to=["BlueLake"], subject="API review needed", body_md="Please check the auth endpoints...", cc=["RedBear"], # Optional bcc=["Overseer"], # Optional thread_id="bd-123", # Optional, for threading importance="normal", # low|normal|high|urgent ack_required=true # Request acknowledgment ) ``` ### reply_message Reply preserving thread. ``` reply_message( project_key="/abs/path/project", message_id=1234, sender_name="BlueLake", body_md="Looks good, one suggestion...", to=["GreenCastle"], # Optional, defaults to original sender cc=["RedBear"], # Optional subject_prefix="Re:" # Default ) ``` ### fetch_inbox Get messages for agent. ``` fetch_inbox( project_key="/abs/path/project", agent_name="GreenCastle", limit=20, since_ts="2025-01-01T00:00:00Z", # Optional urgent_only=false, include_bodies=true ) ``` ### mark_message_read Mark message as read. ``` mark_message_read( project_key="/abs/path/project", agent_name="GreenCastle", message_id=1234 ) ``` ### acknowledge_message Acknowledge receipt (also marks read). ``` acknowledge_message( project_key="/abs/path/project", agent_name="GreenCastle", message_id=1234 ) ``` ### search_messages FTS5 full-text search. ``` search_messages( project_key="/abs/path/project", query='"auth module" AND error', limit=20 ) ``` ### summarize_thread Extract key points and actions. ``` summarize_thread( project_key="/abs/path/project", thread_id="bd-123", include_examples=true, llm_mode=true ) ``` --- ## File Reservations ### file_reservation_paths Reserve files before editing. ``` file_reservation_paths( project_key="/abs/path/project", agent_name="GreenCastle", paths=["src/auth/**/*.ts", "src/middleware/auth.ts"], ttl_seconds=3600, exclusive=true, reason="bd-123" ) ``` **Returns:** `{granted: [...], conflicts: [...]}` Conflicts are advisory — reservations still granted. ### release_file_reservations Release reservations. ``` release_file_reservations( project_key="/abs/path/project", agent_name="GreenCastle", paths=["src/auth/**"], # Optional, releases all if omitted file_reservation_ids=[101] # Optional, by ID ) ``` ### renew_file_reservations Extend TTL. ``` renew_file_reservations( project_key="/abs/path/project", agent_name="GreenCastle", extend_seconds=1800 ) ``` ### force_release_file_reservation Clear stale reservation from another agent. ``` force_release_file_reservation( project_key="/abs/path/project", agent_name="GreenCastle", file_reservation_id=101, note="Agent crashed, clearing stale lock", notify_previous=true ) ``` --- ## Contact Management ### request_contact Request permission to message another agent. ``` request_contact( project_key="/abs/path/project", from_agent="GreenCastle", to_agent="BlueLake", to_project="/abs/path/other", # Optional, for cross-project reason="API coordination", ttl_seconds=604800 # 7 days default ) ``` ### respond_contact Accept or deny contact request. ``` respond_contact( project_key="/abs/path/project", to_agent="BlueLake", from_agent="GreenCastle", accept=true ) ``` ### list_contacts List contact links for agent. ``` list_contacts( project_key="/abs/path/project", agent_name="GreenCastle" ) ``` ### set_contact_policy Set contact policy. ``` set_contact_policy( project_key="/abs/path/project", agent_name="GreenCastle", policy="auto" # open|auto|contacts_only|block_all ) ``` --- ## Macros ### macro_start_session One-call bootstrap. ``` macro_start_session( human_key="/abs/path/project", program="codex-cli", model="YOUR_MODEL", task_description="Auth refactor", file_reservation_paths=["src/auth/**"], inbox_limit=10 ) ``` **Returns:** `{project, agent, file_reservations, inbox}` ### macro_prepare_thread Join existing thread with context. ``` macro_prepare_thread( project_key="/abs/path/project", thread_id="bd-123", program="codex-cli", model="YOUR_MODEL", include_examples=true, inbox_limit=10 ) ``` ### macro_file_reservation_cycle Reserve, work, auto-release. ``` macro_file_reservation_cycle( project_key="/abs/path/project", agent_name="GreenCastle", paths=["src/auth/**"], ttl_seconds=3600, auto_release=true ) ``` ### macro_contact_handshake Contact setup with optional auto-accept. ``` macro_contact_handshake( project_key="/abs/path/project", requester="GreenCastle", target="BlueLake", auto_accept=true, welcome_subject="Coordination request", welcome_body="Let's sync on API changes" ) ``` --- ## Guard Tools ### install_precommit_guard Install git pre-commit hook to enforce file reservations. ``` install_precommit_guard( project_key="/abs/path/project", code_repo_path="/abs/path/project" ) ``` ### uninstall_precommit_guard Remove pre-commit guard. ``` uninstall_precommit_guard(code_repo_path="/abs/path/project") ``` --- ## Health ### health_check Return server readiness status. ``` health_check() ``` **Returns:** `{status: "healthy"}` -
WORKFLOWS.md 3.2 KB
# Agent Mail Coordination Patterns Agent Mail is an optional messaging and file-reservation adapter for an explicitly coordinated multi-writer run. The caller supplies the actors, project, thread, paths, and message. Agent Mail does not select work, assign ownership, decide readiness, validate a candidate, or record completion. ## Start an explicit coordination lane The caller must provide: - absolute project path; - sender and recipient identities; - stable caller-owned thread ID; - exact path patterns and reservation TTL; - the factual message to send. Example: ```text macro_start_session( human_key="/abs/project", program="codex-cli", model="caller-selected" ) file_reservation_paths( project_key="/abs/project", agent_name="GreenCastle", paths=["src/auth/**"], ttl_seconds=3600, exclusive=true, reason="caller-supplied packet auth-surface" ) send_message( project_key="/abs/project", sender_name="GreenCastle", to=["BlueLake"], thread_id="auth-surface", subject="[auth-surface] write scope active", body_md="Reserved src/auth/** for the supplied packet.", ack_required=true ) ``` If a reservation conflicts, report the conflicting paths and holder once. Do not automatically wait, split the packet, retry, or choose a different scope. The caller owns that decision. ## Request an independent review A message can carry a review request, but its acknowledgement or reply is not an AgentOps verdict. Include exact identity and evidence: ```text send_message( project_key="/abs/project", sender_name="GreenCastle", to=["BlueLake"], thread_id="auth-surface", subject="[auth-surface] review request", body_md=""" Candidate manifest: sha256:... Acceptance digest: sha256:... Changed paths: src/auth/oauth.ts, src/auth/oauth_test.ts Evidence: go test ./src/auth/... Please return findings with checked and not-checked scope. """, ack_required=true ) ``` The reviewer may reply with findings and evidence references. Validate remains the sole owner of `verdict.v2`; Agent Mail never turns a reply into PASS. ## Handoff facts Use one thread to report facts needed by another explicit actor: ```text send_message( project_key="/abs/project", sender_name="GreenCastle", to=["BlueLake"], thread_id="auth-surface", subject="[auth-surface] handoff", body_md=""" Candidate manifest: sha256:... Changed paths: src/auth/oauth.ts, src/auth/oauth_test.ts Checks: go test ./src/auth/... (exit 0) Unchecked: external identity provider integration """ ) ``` A handoff carries no implicit ownership, approval, next action, or delivery authority. The caller interprets it. ## Release reservations Release only reservations held by the named actor: ```text release_file_reservations( project_key="/abs/project", agent_name="GreenCastle", paths=["src/auth/**"] ) ``` Releasing a reservation is coordination cleanup, not work completion. ## Failure reporting Return exactly the observed adapter result: - session registration succeeded or failed; - reservation acquired or conflicted, with paths and holder; - message ID and recipients, or send error; - release result. Do not translate transport errors into retry state, queue state, lifecycle status, or an andon. Stop after reporting the facts.
-
-
SKILL.md 6.6 KB
--- name: agent-mail user-invocable: true skill_api_version: 1 hexagonal_role: supporting consumes: - coordination-request produces: - agent-identity - file-reservation - acknowledged-handoff context_rel: - kind: supplier-to with: agent-native metadata: capabilities: [agent_mail] effects: [write_agent_mail_records, install_precommit_guard, authorized_destructive_reset] canonical_status: canonical disposition: keep_optional_adapter tier: execution dependencies: [] description: 'Coordinate selected writers with Agent Mail messages and advisory file reservations. Use when: this adapter is requested; mail does not own tracker status.' practices: - pragmatic-programmer output_contract: factual messaging and reservation adapter results --- # Agent Mail — optional coordination adapter Agent Mail carries messages, acknowledgements, identities, and temporary file reservations. It is not a task tracker, queue, proof ledger, or lifecycle controller. Reservations are **advisory**: they prevent collisions only because every cooperating writer checks them against the same absolute project path, and one writer registered against a different path resolution makes the whole ledger advisory fiction. Agent Mail enforces nothing on a writer that does not check. Named failure mode — **silence-as-status**: reading an unanswered thread as "work stalled" or "work done"; mail silence proves only that no mail arrived. Anti-pattern: widening or renewing a reservation unprompted when a conflict appears. Corrective: report the conflict to the caller as-is; scope and TTL changes are the caller's call. ## Boundary - Skip Agent Mail for a single writer. - The caller supplies the absolute project path, agent identities, thread id, participants, paths, exclusivity, reason, and TTL. - Reservations prevent accidental overlap among cooperating writers. They do not create work ownership or affect Plan, Candidate, or verdict semantics. - Mail silence proves nothing about work status. - A message or acknowledgement is evidence that communication occurred, not evidence that a change is correct or complete. The adapter cannot select AgentOps semantics, issue a binding verdict, or turn factory completion into delivery or validation proof. - Release a reservation, including any `force_release`, only on the caller's explicit request for that exact reservation. Force-release has no autonomous trigger; a conflict is reported, not force-cleared. - Agent Mail never selects work, changes tracker state, commits code, validates, integrates, closes, releases, or delivers work. ## Modes and authority Two disjoint surfaces; do not reach the second from the first: - **Coordination mode (default).** Register identity, reserve/release the caller's paths, send/read/acknowledge the caller's threads. This is the whole of routine use, and all of it writes durable Agent Mail records. - **Admin / disaster-recovery mode (explicitly caller-authorized only).** Installing the git pre-commit guard, `doctor repair`, backup/restore, and the irreversible `clear-and-reset-everything` are a separate mode. Each requires the caller's explicit authorization for that specific operation; none is ever performed as a side effect of coordination. `clear-and-reset-everything` deletes the database and all storage and cannot be undone — never run it, even with `--force`, without an explicit destructive-reset authorization from the caller. ## Surfaces Choose exactly one mailbox owner and access mode for each storage root. When an HTTP/MCP daemon owns the root, use its MCP tools; do not point the direct `am` CLI at the same database. Use the CLI fallback only with a root not owned by a running Agent Mail runtime. A busy mailbox activity lock or a bounded read timeout is a degraded adapter result, not permission to restart the service, repair the database, or silently switch roots. Use the MCP tools when they are present. Otherwise use the self-describing `am` CLI. Pin the intended storage root explicitly, and discover current syntax with `am mail --help`, `am file_reservations --help`, and related group help; do not infer commands from remembered aliases. If a direct macOS read rejects a symlinked snapshot directory such as `/var`, use a caller-scoped, non-symlinked temporary directory for that isolated invocation or report the adapter degraded; never weaken the traversal check. ## One-shot use 1. Confirm that multiple explicitly coordinated writers share the repository. 2. Freeze one storage root and either MCP/server mode or direct-CLI mode; never mix both against the same live database. 3. Register the caller-supplied identity against the same absolute project path. 4. Reserve only the supplied paths, with a bounded TTL. 5. Report conflicts without waiting, narrowing scope, or changing the plan. 6. Send the supplied message once and record its id. 7. Read or acknowledge only the requested thread. 8. Before the caller advances a declared transition, verify every acknowledgement-required message in that transition has the intended recipient acknowledgement. Later traffic is not an implicit acknowledgement. 9. Release only reservations the caller explicitly asks to release. ## Output Return the project, identity, thread/message ids, reservation ids and paths (with their TTLs), conflicts, and timestamps. The caller owns all subsequent decisions. Terminal outcomes are explicit, never silent: - **Adapter unavailable** — neither the MCP tools nor the `am` CLI is present: report that Agent Mail is unavailable and stop. Do not fall back to hand-written coordination or treat the absence as "no conflicts". - **Reservation conflict** — report the conflicting reservation as-is; do not narrow, widen, renew, or force-release it. - **Mailbox ownership conflict** — a daemon and direct CLI contend for one storage root: report the lock owner/mode and stop; do not restart, repair, or bypass the lock as a coordination side effect. - **Required acknowledgement pending** — report the exact message and intended recipient and stop the dependent transition. Do not infer acknowledgement from a later reply or repair it after validation. - **Timeout / degraded surface** — report the operation as timed out or degraded with what was and was not observed; a timeout is evidence, not "done". - **Cleanup** — reservations released this session are listed by id; any left in place (still holding a TTL) are named so the caller can see what remains. ## References - [CLI and MCP surface notes](references/TOOLS.md) - [Coordination patterns](references/WORKFLOWS.md) - [Troubleshooting](references/RECOVERY.md)
Comments (0)
Sign in to join the conversation.
Reviews (0)
No reviews yet.
No comments yet.