# AGENTS.md

> **Scope:** These instructions apply to the entire repository.
>
> **Maintenance rule:** Keep this file accurate and concise. It is a map and a shared contract, not a changelog. Replace guidance that is no longer true.

## Purpose

This repository contains an experimental, modular system for exploring Nostr through an LLM-driven interface. It combines an agent host, an MCP gateway, several MCP backends, an HTTP-to-MCP bridge, and a browser-based explorer.

Use this file as the starting point before changing code. Then read the nearest component-level `AGENTS.md` for the directory you are working in.

## Instruction precedence

Instructions are hierarchical:

1. This root `AGENTS.md` defines repository-wide expectations.
2. A nested `AGENTS.md` adds or overrides rules for its own directory tree.
3. The most specific applicable instruction wins when two rules conflict.
4. Existing code, tests, runtime contracts, and configuration remain the source of truth when documentation is incomplete.

Do not assume that a rule from one component applies to another component unless this file says so explicitly.

## Start here

Read the component guide that matches the area you are changing:

| Path | Responsibility | Local instructions |
|---|---|---|
| `host/agent0/` | Agent host and LLM orchestration | [`host/agent0/AGENTS.md`](host/agent0/AGENTS.md) |
| `gateway_mcps/` | Aggregates MCP backends and exposes one MCP gateway | [`gateway_mcps/AGENTS.md`](gateway_mcps/AGENTS.md) |
| `exec_mcp/` | Plain HTTP-to-MCP tool execution bridge | [`exec_mcp/AGENTS.md`](exec_mcp/AGENTS.md) |
| `mcp_servers/nostr_mcp/` | Nostr-facing MCP tools | [`mcp_servers/nostr_mcp/AGENTS.md`](mcp_servers/nostr_mcp/AGENTS.md) |
| `mcp_servers/nostr_db_mcp/` | Nostr ingestion, storage, tracking, querying, and resources | [`mcp_servers/nostr_db_mcp/AGENTS.md`](mcp_servers/nostr_db_mcp/AGENTS.md) |
| `mcp_servers/nostr_explorer_mcp/` | Dedicated Nostr web GUI, per-session agents, WebSocket protocol, and its own presentation controls | [`mcp_servers/nostr_explorer_mcp/AGENTS.md`](mcp_servers/nostr_explorer_mcp/AGENTS.md) |
| `mcp_servers/user_mcp/` | Human-facing “show and listen” layer: presents data to the user and returns the user's next instruction | [`mcp_servers/user_mcp/AGENTS.md`](mcp_servers/user_mcp/AGENTS.md) |

When a change crosses component boundaries, read every affected local guide before editing.

## System map

The typical runtime flow is:

```text
Browser / user
      │
      ▼
Nostr Explorer or Agent Host
      │
      ▼
MCP Gateway
      │
      ├── User MCP ──► the user's browser (its own HTTP + WebSocket channel)
      ├── Nostr MCP
      ├── Nostr DB MCP
      └── other configured MCP backends
```

`user_mcp` is how an agent reaches the human. It is a normal MCP backend behind the gateway, but its own output path goes straight to the user's browser: `present_data` shows a view, `what_next` blocks until the user's next instruction (transcribed speech plus the elements they clicked) comes back. Data shown to the user therefore leaves the system through `user_mcp`, not through the gateway's reply to the host.

`exec_mcp` is a separate adapter for callers that need to invoke MCP tools over plain HTTP. It is not the gateway and does not replace the normal MCP protocol path.

Keep these boundaries intact:

- The **host/explorer** owns the agent loop and agent behavior.
- **`user_mcp`** owns generic user-facing presentation and input capture for agents.
- The **gateway** owns backend aggregation, routing, lifecycle, and public MCP exposure.
- Individual **MCP servers** own domain behavior and data contracts.
- The **HTTP bridge** only translates HTTP tool calls into MCP calls.

Do not move business logic into transport or routing layers merely because it is convenient.

## Repository-wide rules

### Preserve contracts

Treat these as public contracts unless the task explicitly changes them:

- MCP tool names, schemas, resources, and URI formats.
- WebSocket and HTTP request/response payloads.
- Configuration keys and default ports.
- Database schemas and persisted data semantics.
- Error behavior relied on by callers or tests.

If a contract must change, update all producers, consumers, tests, examples, and relevant `AGENTS.md` files in the same change.

### Prefer explicit failure

Do not silently ignore invalid state, malformed data, routing ambiguity, collisions, or broken invariants. Raise a specific error unless a local guide explicitly documents best-effort behavior.

Error messages should identify:

- what failed,
- which component or identifier was involved,
- and what invariant or input was violated.

### Respect component isolation

Most components have their own virtual environment, dependencies, startup script, tests, and port. Avoid introducing hidden cross-directory imports or undeclared runtime coupling.

When sharing behavior is genuinely necessary, define a clear interface rather than importing private implementation details from a sibling component.

### Keep changes focused

- Make the smallest coherent change that solves the task.
- Do not perform unrelated rewrites, translations, renames, or formatting sweeps.
- Follow the language and naming style already used in the file being edited.
- Preserve intentionally unusual architecture unless the task explicitly calls for redesign.
- Do not replace hard-won edge-case handling with a simpler implementation without proving equivalent behavior.

### Async and lifecycle discipline

This repository contains long-lived sessions, connection pools, WebSockets, subscriptions, reconnect loops, and background tasks.

For lifecycle changes, verify:

- startup and shutdown paths,
- cancellation behavior,
- reconnect behavior,
- lock ownership and ordering,
- cleanup of sessions, subscriptions, clients, and tasks,
- behavior after partial failure.

Never add an untracked background task when its owner and shutdown path are unclear.

### Security and secrets

- Never commit API keys, tokens, private keys, credentials, or local secrets.
- Do not log secrets or full credential-bearing configuration.
- Treat Nostr private keys and LLM provider credentials as sensitive.
- Use existing configuration mechanisms; document new required variables or keys.

## Working method

Before editing:

1. Read this file and the nearest local `AGENTS.md`.
2. Identify the component entrypoint, tests, configuration, and external contracts involved.
3. Search for every caller and consumer of the behavior being changed.
4. Confirm whether the change affects another component.

While editing:

1. Preserve separation of concerns.
2. Add or update tests near the changed behavior.
3. Keep failure modes explicit.
4. Update documentation when a documented invariant or contract changes.

Before finishing:

1. Run the narrowest relevant tests first.
2. Run the component's broader test suite when practical.
3. Check startup/import failures for every modified component.
4. Review logs and error paths, not only the happy path.
5. Verify that generated, cached, secret, environment, database, and log files were not added accidentally.
6. Write down any important fact you had to discover yourself, as described in [Record missing knowledge](#record-missing-knowledge).

## Testing

There is no single repository-wide test command documented here because components are independently runnable and may use different conventions. Use the commands in each local `AGENTS.md`, `README.md`, or component test directory.

At minimum, a change should include:

- a regression test for a bug fix,
- contract tests for protocol or schema changes,
- failure-path coverage for validation and lifecycle changes,
- and an integration test when behavior crosses a process or MCP boundary.

Do not weaken or delete a failing test merely to make a change pass unless the test asserts behavior that is intentionally being replaced.

## Documentation expectations

Update the applicable `AGENTS.md` when you change a durable fact that future agents need to know, such as:

- architecture or ownership boundaries,
- a protocol or schema contract,
- a required startup dependency,
- a non-obvious invariant,
- a recurring failure mode,
- a test convention,
- or an intentional design trade-off.

### Record missing knowledge

Documentation gaps are also a documentation task. If during development you discover that important information is missing from an `AGENTS.md` — something you had to reconstruct from code, tests, configuration, or trial and error, and that the next agent would need too — note it as you go and add it to the appropriate `AGENTS.md` before finishing, even when the task itself changed nothing about that fact.

This applies to, for example:

- an undocumented invariant, precondition, or ordering requirement,
- a startup dependency, port, or configuration key you had to discover,
- a non-obvious reason why code is shaped the way it is,
- a failure mode or debugging step that cost you time,
- a test or tooling command that is not written down anywhere.

Add the fact to the nearest applicable local guide; only shared rules and navigation belong in this root file. Write it as a durable statement of current behavior, not as a note about your own investigation. If a fact is genuinely unclear rather than merely undocumented, say so explicitly instead of guessing.

Do not add chronological notes such as “previously,” “recently,” or “changed in this commit.” Describe only the current state.

Keep detailed component knowledge in the nearest local guide. Keep this root file limited to shared rules and navigation.

## Cross-component checklist

Use this checklist when a change touches more than one service:

- Are tool names and argument schemas identical on both sides?
- Are resource URIs and payload formats preserved?
- Are ports and backend identifiers configured consistently?
- Does reconnect behavior still work after either side restarts?
- Are errors propagated in a form the caller understands?
- Are UI approval, visibility, and presentation guarantees preserved?
- Are all affected local guides and tests updated?

## Known architectural cautions

- The gateway and the HTTP executor are different services with different responsibilities and listen ports.
- Resource URIs may have stricter identity and collision rules than tool names; read the gateway guide before changing routing.
- Nostr database tracking and ingestion contain asymmetric, stateful behavior; read the database guide before simplifying it.
- Two different components render to a browser, and they are not interchangeable. `user_mcp` is the general-purpose presentation and speech-input layer any agent can call as an MCP tool; `nostr_explorer_mcp` is a self-contained Nostr GUI with its own per-tab sessions and WebSocket protocol. Decide which one a user-facing change belongs to before editing either.
- Explorer sessions have user-facing approval, aliasing, billing, and WebSocket contracts; read the explorer guide before changing agent capabilities or result handling.
- Several components intentionally reconnect and retain long-lived client/session state. A locally simpler one-shot connection may be a functional regression.

## Definition of done

A change is complete when:

- the requested behavior works,
- relevant tests pass,
- failure and cleanup paths remain correct,
- public contracts are preserved or deliberately migrated,
- configuration and documentation are current,
- and no unrelated artifacts or secrets are included.
