mercury-agent 0.16.1 → 0.16.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -0
- package/docs/README.md +50 -0
- package/docs/authoring-profiles.md +8 -0
- package/docs/behavior-layers.md +204 -0
- package/docs/extensions.md +2 -0
- package/docs/goals/football-reporter-profile/decisions.md +479 -0
- package/docs/goals/football-reporter-profile/goal.md +91 -0
- package/docs/goals/football-reporter-profile/roadmap.md +196 -0
- package/docs/goals/whatsapp-bot-hardening/README.md +43 -0
- package/docs/goals/whatsapp-bot-hardening/archive/ambient-group-context.md +211 -0
- package/docs/goals/whatsapp-bot-hardening/archive/command-routing-consistency.md +210 -0
- package/docs/goals/whatsapp-bot-hardening/archive/destructive-command-guards.md +218 -0
- package/docs/goals/whatsapp-bot-hardening/archive/docs-extension.md +182 -0
- package/docs/goals/whatsapp-bot-hardening/archive/handoff-2026-08-09.md +588 -0
- package/docs/goals/whatsapp-bot-hardening/archive/media-size-and-silent-drop.md +178 -0
- package/docs/goals/whatsapp-bot-hardening/archive/member-memory.md +199 -0
- package/docs/goals/whatsapp-bot-hardening/archive/message-author-attribution.md +211 -0
- package/docs/goals/whatsapp-bot-hardening/archive/run-from-source-switchover.md +212 -0
- package/docs/goals/whatsapp-bot-hardening/archive/setup-plan-2026-08-06.md +1117 -0
- package/docs/goals/whatsapp-bot-hardening/decisions.md +200 -0
- package/docs/goals/whatsapp-bot-hardening/goal.md +75 -0
- package/docs/goals/whatsapp-bot-hardening/open-threads.md +396 -0
- package/docs/goals/whatsapp-bot-hardening/roadmap.md +245 -0
- package/docs/memory.md +30 -0
- package/docs/profile-guide.md +483 -0
- package/docs/refactor/.gitkeep +0 -0
- package/docs/refactor/archive/.gitkeep +0 -0
- package/docs/refactor/audits/.gitkeep +0 -0
- package/docs/refactor/backlog/.gitkeep +0 -0
- package/docs/skills-guide.md +154 -0
- package/examples/extensions/README.md +1 -0
- package/examples/extensions/feed-watch/config.ts +354 -0
- package/examples/extensions/feed-watch/digest.ts +344 -0
- package/examples/extensions/feed-watch/feeds.ts +341 -0
- package/examples/extensions/feed-watch/index.ts +302 -0
- package/examples/extensions/feed-watch/items.ts +171 -0
- package/examples/extensions/feed-watch/match.ts +107 -0
- package/examples/extensions/feed-watch/prompts/verify.md +35 -0
- package/examples/extensions/feed-watch/skill/SKILL.md +128 -0
- package/examples/extensions/feed-watch/watch.ts +548 -0
- package/examples/extensions/longview/hook.ts +179 -16
- package/examples/extensions/longview/index.ts +13 -2
- package/examples/extensions/longview/prompts/summarize.md +3 -2
- package/examples/extensions/longview/render/telegraph-nodes.ts +21 -1
- package/examples/extensions/longview/summarize.ts +57 -14
- package/examples/extensions/napkin/index.ts +334 -86
- package/examples/extensions/napkin/pi-spawn.ts +196 -0
- package/examples/extensions/pinchtab/index.ts +37 -4
- package/examples/extensions/pinchtab/lib/session-injector.ts +31 -9
- package/examples/extensions/pinchtab/skill/SKILL.md +29 -0
- package/examples/profiles/_template/AGENTS.md +138 -0
- package/examples/profiles/_template/README.md +65 -0
- package/examples/profiles/_template/config.yaml +57 -0
- package/examples/profiles/_template/tasks/daily.md +32 -0
- package/examples/profiles/football-reporter/AGENTS.md +219 -0
- package/examples/profiles/football-reporter/README.md +138 -0
- package/examples/profiles/football-reporter/config.yaml +184 -0
- package/examples/profiles/football-reporter/seed/MEMORY.md +42 -0
- package/examples/profiles/football-reporter/seed/episodes/barcelona-2026-27.md +25 -0
- package/examples/profiles/football-reporter/seed/episodes/beitar-jerusalem-2026-27.md +25 -0
- package/examples/profiles/football-reporter/seed/episodes/maccabi-haifa-2026-27.md +24 -0
- package/examples/profiles/football-reporter/seed/episodes/man-united-2026-27.md +26 -0
- package/examples/profiles/football-reporter/seed/episodes/real-madrid-2026-27.md +25 -0
- package/examples/profiles/football-reporter/seed/napkin-distill.md +55 -0
- package/examples/profiles/football-reporter/tasks/daily-article.md +142 -0
- package/package.json +8 -5
- package/src/adapters/whatsapp.ts +20 -1
- package/src/agent/container-entry.ts +43 -6
- package/src/agent/container-runner.ts +32 -2
- package/src/cli/build-image-tags.ts +34 -0
- package/src/cli/mercury.ts +50 -4
- package/src/cli/mrctl.ts +9 -1
- package/src/config.ts +5 -3
- package/src/core/handler.ts +13 -1
- package/src/core/routes/config-builtin.ts +7 -0
- package/src/core/routes/dashboard.ts +117 -5
- package/src/core/routes/tasks.ts +28 -0
- package/src/core/runtime.ts +94 -13
- package/src/core/task-scheduler.ts +103 -12
- package/src/extensions/catalog.ts +9 -0
- package/src/profile/space-profile.ts +780 -0
- package/src/storage/db.ts +215 -0
- package/src/types.ts +56 -0
package/README.md
CHANGED
|
@@ -217,6 +217,9 @@ mercury setup --profile https://github.com/user/mercury-stock-agent
|
|
|
217
217
|
# Create from local directory
|
|
218
218
|
mercury setup --profile ./my-profiles/ml-assistant
|
|
219
219
|
|
|
220
|
+
# Apply a profile non-interactively (deploy scripts, existing projects)
|
|
221
|
+
mercury profiles apply ./my-profiles/ml-assistant
|
|
222
|
+
|
|
220
223
|
# List available profiles
|
|
221
224
|
mercury profiles list
|
|
222
225
|
|
|
@@ -224,6 +227,8 @@ mercury profiles list
|
|
|
224
227
|
mercury profiles export ./my-profile
|
|
225
228
|
```
|
|
226
229
|
|
|
230
|
+
Building one for a specific use-case — what goes in `AGENTS.md`, how to keep it accurate, memory, skills, tasks, permissions, testing — is covered in [docs/profile-guide.md](docs/profile-guide.md). A single space inside a general bot gets a **space profile** instead (`scripts/space-profile.ts`, scaffold in [`examples/profiles/_template/`](examples/profiles/_template/)).
|
|
231
|
+
|
|
227
232
|
---
|
|
228
233
|
|
|
229
234
|
## CLI
|
|
@@ -513,6 +518,7 @@ mrctl config set trigger_patterns "@Bot,Bot"
|
|
|
513
518
|
- [Authentication](docs/auth/overview.md)
|
|
514
519
|
- [Message pipeline](docs/pipeline.md)
|
|
515
520
|
- [Memory system](docs/memory.md)
|
|
521
|
+
- **Building a bot for a use-case:** [Profile guide](docs/profile-guide.md) · [Behaviour layers](docs/behavior-layers.md) · [Skills guide](docs/skills-guide.md) · [Applicative profile contract](docs/authoring-profiles.md)
|
|
516
522
|
- [Scheduled tasks](docs/scheduler.md)
|
|
517
523
|
- [Permissions](docs/permissions.md)
|
|
518
524
|
- [Media handling](docs/media/overview.md)
|
package/docs/README.md
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Mercury — docs
|
|
2
|
+
|
|
3
|
+
Product docs, planning docs, ops runbooks and workflow scaffolding for
|
|
4
|
+
[mercury](https://github.com/Avishai-Tsabari/mercury). All of it lives in this
|
|
5
|
+
repository, tracked normally.
|
|
6
|
+
|
|
7
|
+
## Layout
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
docs/
|
|
11
|
+
configuration.md, pipeline.md, auth/, security/, ... product & reference docs
|
|
12
|
+
runbooks/ operational runbooks (release steps, OAuth setup)
|
|
13
|
+
goals/{slug}/ multi-milestone goals (goal, roadmap, decisions)
|
|
14
|
+
ideas/{slug}.md raw ideas, not yet planned
|
|
15
|
+
backlog/{slug}.md goal + architecture approved, not started
|
|
16
|
+
in-progress/{slug}.md active implementation
|
|
17
|
+
archive/{slug}.md shipped or abandoned
|
|
18
|
+
bugs/{slug}.md open bug reports
|
|
19
|
+
debug/{severity}/ bug post-mortems
|
|
20
|
+
refactor/ audits, active refactor docs, archive
|
|
21
|
+
notes/, templates/, html-slides/, pending-updates/
|
|
22
|
+
ROADMAP.md single source of truth for priority
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Content rule
|
|
26
|
+
|
|
27
|
+
The repo is private, but "private" is not "unreviewed". For everything under
|
|
28
|
+
`docs/`:
|
|
29
|
+
|
|
30
|
+
- **Name secrets, never paste values.** `MERCURY_ANTHROPIC_API_KEY`, not the key.
|
|
31
|
+
- **Keep third-party identifiers out unless they carry the finding.** A phone
|
|
32
|
+
number, WhatsApp JID or LID belongs in a doc only when the identifier *is* the
|
|
33
|
+
evidence — a post-mortem about LID resolution may quote one; a setup guide may
|
|
34
|
+
not.
|
|
35
|
+
|
|
36
|
+
## History
|
|
37
|
+
|
|
38
|
+
Until 2026-08-19 the scaffolding lived in a second private repository,
|
|
39
|
+
`saharw01/mercury-planning`, whose working tree *was* this directory — a
|
|
40
|
+
workaround from when mercury was public and planning docs were kept out of it by
|
|
41
|
+
policy (PR #22, 2026-08-10).
|
|
42
|
+
|
|
43
|
+
That is over. The repo is private, PRs #46/#47 brought `docs/debug/` and
|
|
44
|
+
`docs/runbooks/` back under version control, and the rest of the scaffolding
|
|
45
|
+
followed. The planning repo's 44 commits were merged in with `-X subtree=docs`,
|
|
46
|
+
so authorship and per-file history survive; `git log --follow` traces through
|
|
47
|
+
both the original subtree split (mercury `d5d2aa6`) and the re-merge.
|
|
48
|
+
|
|
49
|
+
There is one repo and one `git status` again. Nothing here needs a second remote,
|
|
50
|
+
a nested `.git`, or an allowlist in `.git/info/exclude`.
|
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Authoring Applicative Profiles
|
|
2
2
|
|
|
3
|
+
> This page is the **contract** — manifest, broker, permissions. For *how to
|
|
4
|
+
> design* a profile that is accurate and stays in character (the layer map,
|
|
5
|
+
> facts inventory, `AGENTS.md` shape, memory, skills, tasks, testing) read
|
|
6
|
+
> [`profile-guide.md`](profile-guide.md) first; for what the model actually
|
|
7
|
+
> receives, [`behavior-layers.md`](behavior-layers.md). Per-space profiles
|
|
8
|
+
> (one space inside a general bot) use `scripts/space-profile.ts` instead of
|
|
9
|
+
> this manifest — see `examples/profiles/_template/`.
|
|
10
|
+
|
|
3
11
|
The contract for building a **profile** — a package of deterministic business
|
|
4
12
|
logic that wraps raw capabilities (Calendar, email, …) and scopes what members
|
|
5
13
|
can do. Mercury (this repo) provides the schema, loader, permission scoping, and
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
# Behaviour layers — where a rule lives, and what the model actually receives
|
|
2
|
+
|
|
3
|
+
Every agent run is assembled from several layers written by different people
|
|
4
|
+
at different times: the platform prompt baked into the image, an optional
|
|
5
|
+
applicative profile, the owner's global character, the global `AGENTS.md`, the
|
|
6
|
+
space `AGENTS.md`, space preferences, space config, task prompts, and the
|
|
7
|
+
memory files in the workspace. Most "the bot ignores my instruction" reports
|
|
8
|
+
are two of these layers disagreeing. This page is the verified map — what is
|
|
9
|
+
sent, in what order, who owns it, and when a change takes effect.
|
|
10
|
+
|
|
11
|
+
Verified against `src/agent/container-entry.ts`, `src/core/runtime.ts`,
|
|
12
|
+
`src/storage/db.ts` and pi 0.84.2's `resource-loader.js` / `system-prompt.js`
|
|
13
|
+
(inside the agent image) on 2026-08-21. Re-verify by grepping the image, not
|
|
14
|
+
the repo, after a pi upgrade.
|
|
15
|
+
|
|
16
|
+
## 1. The system prompt, top to bottom
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
1. pi preamble ............................ image container-entry.ts buildSystemPrompt
|
|
20
|
+
"You are an expert AI assistant…", tool list, "Be concise"
|
|
21
|
+
(override mode; OVERRIDE_PI_SYSTEM_PROMPT)
|
|
22
|
+
2. Mercury platform block .................. image container-entry.ts buildMercuryAdditions
|
|
23
|
+
inbox/outbox · "You are <bot_username>; read /docs/mercury"
|
|
24
|
+
## Permissions & Security ("Permission denied → simply inform the user")
|
|
25
|
+
## Moderation ("warn first, then mute" — only for a caller holding mutes.mute)
|
|
26
|
+
## Environment Variables
|
|
27
|
+
## Current model capabilities
|
|
28
|
+
## Memory (MEMORY.md, <active_episodes>, <members>, member notes)
|
|
29
|
+
## Run budget (tools-capable models only)
|
|
30
|
+
## Destructive Operations — Confirmation Required
|
|
31
|
+
## Presenting tool results ("simple lists", "never show JSON/commands")
|
|
32
|
+
## Character (mrctl character flow + "standing instruction → set a preference"
|
|
33
|
+
— only for a caller holding prefs.set)
|
|
34
|
+
reply-anchor sentence (swipe-replies only)
|
|
35
|
+
3. MERCURY_EXT_SYSTEM_PROMPT ............... host runtime.ts ~1700-1760
|
|
36
|
+
a. extension before_container `systemPrompt` fragments
|
|
37
|
+
b. applicative profile `profile_prompt` (.mercury/active-profile.json)
|
|
38
|
+
c. "## Bot Character (set by the owner — applies to all conversations)"
|
|
39
|
+
(project_config.character;
|
|
40
|
+
skipped when persona.exclusive=true)
|
|
41
|
+
d. space `system_prompt` (space_config, dashboard-set)
|
|
42
|
+
4. <project_context> ....................... pi resource-loader.js loadProjectContextFiles
|
|
43
|
+
<project_instructions path="/home/mercury/.pi/agent/AGENTS.md"> ← .mercury/global/AGENTS.md
|
|
44
|
+
(not mounted when persona.exclusive=true)
|
|
45
|
+
<project_instructions path="/spaces/<space>/AGENTS.md"> ← the space AGENTS.md
|
|
46
|
+
(pi walks from cwd to /; only the space dir is mounted, so only that
|
|
47
|
+
file and the global one exist. AGENTS.override.md / CLAUDE.md are
|
|
48
|
+
accepted names too; AGENTS.md is the convention.)
|
|
49
|
+
5. <available_skills> ...................... pi skills.js formatSkillsForPrompt
|
|
50
|
+
name + description + SKILL.md path for every skill under
|
|
51
|
+
/home/mercury/.pi/agent/skills/** ← .mercury/global/skills/ (extension + built-in skills)
|
|
52
|
+
/spaces/<space>/.pi/skills/** ← space-local skills
|
|
53
|
+
6. "Current working directory: /spaces/<space>"
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Two consequences worth reading twice:
|
|
57
|
+
|
|
58
|
+
- **Layers 1–3 are prose the model treats as equally authoritative.** Nothing
|
|
59
|
+
ranks "space AGENTS.md" above "## Moderation". When two of them speak to the
|
|
60
|
+
same subject the outcome is a coin flip weighted towards whichever is more
|
|
61
|
+
specific and later — and the platform text itself says so: *"a per-space
|
|
62
|
+
rule that is meant to override a global one has to say so in words rather
|
|
63
|
+
than rely on being more specific."* The only reliable override is an
|
|
64
|
+
explicit sentence naming what it overrides, plus deleting the competing
|
|
65
|
+
rule wherever you control it.
|
|
66
|
+
- **Layer 2 is mostly unconditional, and two voices are removable.** Every
|
|
67
|
+
space receives the security text, the destructive-ops rule and the "simple
|
|
68
|
+
lists, never raw output" paragraph. Two paragraphs are *capability* text
|
|
69
|
+
and are emitted only when the caller can act on them: "## Moderation" for a
|
|
70
|
+
caller holding `mutes.mute`, "## Character" (the preference / character
|
|
71
|
+
flow) for a caller holding `prefs.set` — a member without `prefs.set` is no
|
|
72
|
+
longer told that "a standing instruction → set a preference". And a space
|
|
73
|
+
that owns its standard can set `persona.exclusive=true` (`space_config`,
|
|
74
|
+
profile-owned): the host then leaves the owner's Bot Character (3c) out of
|
|
75
|
+
its prompt and does not mount the global `AGENTS.md` (4), so the space file
|
|
76
|
+
is the only persona left. Everything that still reaches such a space (the
|
|
77
|
+
platform text, skills, a per-space `system_prompt`) is unchanged. A persona
|
|
78
|
+
that contradicts what remains (a reporter who must not offer lists) still
|
|
79
|
+
has to say so in its `AGENTS.md`, in words.
|
|
80
|
+
|
|
81
|
+
## 2. The user prompt, top to bottom
|
|
82
|
+
|
|
83
|
+
Built by `buildPrompt()` in `container-entry.ts`:
|
|
84
|
+
|
|
85
|
+
```
|
|
86
|
+
<caller id name role space/>
|
|
87
|
+
<run_budget>…</run_budget> wall clock for this run
|
|
88
|
+
<episodic_memory>…</episodic_memory> /spaces/<space>/MEMORY.md, verbatim, if present
|
|
89
|
+
<active_episodes>…</active_episodes> knowledge/episodes/*.md, keyword-scored (see §5)
|
|
90
|
+
<history>…</history> sliding window of stored turns (see §4)
|
|
91
|
+
<ambient_messages>…</ambient_messages> overheard group messages (ambient.enabled)
|
|
92
|
+
<members>…</members> space_roles — authoritative id→name→role
|
|
93
|
+
<member_notes>…</member_notes> knowledge/members/<id>.md, ≤6000 chars
|
|
94
|
+
<preferences>…</preferences> space_preferences rows
|
|
95
|
+
<attachments>…</attachments>
|
|
96
|
+
<reply_anchor>…</reply_anchor> swipe-replies only
|
|
97
|
+
<the prompt> chat message, or the task prompt, plus any
|
|
98
|
+
before_container promptAppend (e.g. a digest)
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
A scheduled task uses exactly the same assembly; its prompt row is "the
|
|
102
|
+
prompt", and it runs as the caller who created it.
|
|
103
|
+
|
|
104
|
+
## 3. Ownership, surface, and when a change lands
|
|
105
|
+
|
|
106
|
+
| Layer | Owner | Set from | Takes effect |
|
|
107
|
+
|---|---|---|---|
|
|
108
|
+
| pi preamble, Mercury platform block | mercury (code) | `src/agent/container-entry.ts` | **agent image rebuild** (`container/build.sh`), not a restart |
|
|
109
|
+
| `profile_prompt`, `member_permissions` | deploy (applicative profile) | `mercury profiles apply <dir>` → `.mercury/active-profile.json` | **restart** (read at startup) |
|
|
110
|
+
| Bot Character | bot owner (global admin) | `mrctl character set --file`, `PUT /api/character`, dashboard | next run; left out of a `persona.exclusive` space |
|
|
111
|
+
| space `system_prompt` | space admin | dashboard Spaces settings (`space_config.system_prompt`) | next run |
|
|
112
|
+
| global `AGENTS.md` | deploy | `.mercury/global/AGENTS.md` (written by `mercury init` from `resources/templates/AGENTS.md`, overwritten by an applicative profile's `agents_md`) | next run (mounted `:ro`); not mounted for a `persona.exclusive` space |
|
|
113
|
+
| space `AGENTS.md` | space profile / operator | `.mercury/spaces/<space>/AGENTS.md`; `scripts/space-profile.ts apply` | next run (mounted per run) |
|
|
114
|
+
| space preferences | space admin (`prefs.set`) | `mrctl prefs set/delete`; ≤500 chars each, ≤50 per space | next run |
|
|
115
|
+
| space config (`trigger.*`, `context.*`, `ambient.enabled`, `persona.exclusive`, `role.<r>.permissions`, `<ext>.<key>`, `model.active`, `system_prompt`) | space admin / dashboard / profile | `mrctl config set`, dashboard, `space-profile apply` (`extension_config`) | next run (per-run read) |
|
|
116
|
+
| task prompts | whoever owns the `tasks` row | `mrctl tasks create`, dashboard, `space-profile apply` (`tasks:`) | next scheduled run |
|
|
117
|
+
| `MEMORY.md`, `knowledge/**` | the agent (and napkin's jobs) | `write` tool in-container; host edits | next run |
|
|
118
|
+
| extension skills | extension | `mercury.skill("./skill")` → copied to `.mercury/global/skills/<name>/` at startup | **restart** |
|
|
119
|
+
| space-local skills | operator / profile | `.mercury/spaces/<space>/.pi/skills/<name>/SKILL.md` | next run |
|
|
120
|
+
| `mercury.yaml` (`model.chain`, `context.window_size` default, `agent.trace_runs`, `extensions:` defaults) | operator | file + restart; `MERCURY_*` env wins over YAML | restart (some keys, e.g. `model.active`, are per-run) |
|
|
121
|
+
|
|
122
|
+
"Next run" means the running bot does not need a restart. Two traps:
|
|
123
|
+
|
|
124
|
+
- A restart never redeploys anything in layer 1 — `container-entry.ts` is
|
|
125
|
+
baked into the image. Verify by grepping the image
|
|
126
|
+
(`docker run --rm --entrypoint grep <image> -c "<marker>" /path`), never
|
|
127
|
+
the repo.
|
|
128
|
+
- `MERCURY_*` env overrides `mercury.yaml`; a YAML edit can silently do
|
|
129
|
+
nothing.
|
|
130
|
+
|
|
131
|
+
## 4. The history window
|
|
132
|
+
|
|
133
|
+
- `context.mode` is a per-space key. `main` and DM auto-spaces are seeded
|
|
134
|
+
`context`; **any other space defaults to `clear`** (no history at all — only
|
|
135
|
+
the reply chain when someone swipe-replies). Set it explicitly.
|
|
136
|
+
- `context.window_size` (default 10 — `config.ts contextWindowSize`) counts
|
|
137
|
+
**user turns**: `getRecentTurns` takes the newest `turnCount*5` non-ambient
|
|
138
|
+
rows after the compact boundary and cuts at the Nth user row. Assistant rows
|
|
139
|
+
ride along. Scheduled runs are user rows too, so a space with six
|
|
140
|
+
scheduled runs a day spends most of its window on procedure text.
|
|
141
|
+
- A swipe-reply halves the window (`floor(window/2)`) and prepends the
|
|
142
|
+
replied-to chain (`context.reply_chain_depth`).
|
|
143
|
+
- `mrctl compact` moves the boundary permanently; `mrctl clear` clears the
|
|
144
|
+
next run only; `mrctl recall "<words>"` is a substring search over the
|
|
145
|
+
whole stored history for anything outside the window.
|
|
146
|
+
- Ambient messages have their own budget (30 rows) and do not compete with
|
|
147
|
+
turns.
|
|
148
|
+
|
|
149
|
+
The window is a *recent-conversation* mechanism, not a memory. Anything the
|
|
150
|
+
bot must get right a week later belongs in a file (§5), not in the hope that
|
|
151
|
+
it is still inside the window.
|
|
152
|
+
|
|
153
|
+
## 5. Memory surfaces (what is injected, when)
|
|
154
|
+
|
|
155
|
+
| Surface | File | Injected | Condition |
|
|
156
|
+
|---|---|---|---|
|
|
157
|
+
| Episodic memory | `MEMORY.md` in the space dir | every run, verbatim, as `<episodic_memory>` | file exists and is non-empty. No size cap is enforced — the prompt asks for ~1500 tokens |
|
|
158
|
+
| Active episodes | `knowledge/episodes/*.md` | per run, as `<active_episodes>`, ≤800 tokens | frontmatter `status: active|cooling`, `keywords: ["…"]` (JSON array); score = keyword overlap × (active 1.0 / cooling 0.5) × log(mentions+1); body = `summary:` + `## Current State` |
|
|
159
|
+
| Member notes | `knowledge/members/<id>.md` | per run, as `<member_notes>` | `<id>` = platform id with `/`→`_`; ≤6000 chars total |
|
|
160
|
+
| Members | `space_roles` table | per run, as `<members>` | always; authoritative identity |
|
|
161
|
+
| Preferences | `space_preferences` | per run, as `<preferences>` | always |
|
|
162
|
+
| Vault entities | `knowledge/{people,projects,references,daily}/` | **not injected** | the agent must `read`/`napkin search` them; napkin's distillation job writes them |
|
|
163
|
+
| Anything else in the workspace | `knowledge/*.md`, `outbox/`, … | **not injected** | the agent reads it only if a rule tells it to (e.g. the football profile's `knowledge/push-log.md`) |
|
|
164
|
+
|
|
165
|
+
So: the only *always-on* memories are `MEMORY.md`, preferences and member
|
|
166
|
+
notes. Episodes need keywords that will actually appear in future messages.
|
|
167
|
+
Everything else is opt-in by instruction.
|
|
168
|
+
|
|
169
|
+
## 6. Which layer for which kind of rule
|
|
170
|
+
|
|
171
|
+
| Kind of rule | Put it in | Not in |
|
|
172
|
+
|---|---|---|
|
|
173
|
+
| Who the bot is in this space, register, what it covers, sourcing and accuracy standard, formats, when it stays silent | space `AGENTS.md` | preferences (500-char blocks in the user prompt, no structure, easy to contradict) |
|
|
174
|
+
| A procedure: when it runs, what it produces, where it goes | the task prompt (`tasks/*.md` in a space profile) | `AGENTS.md` (a task prompt never repeats an editorial rule; `AGENTS.md` never describes a schedule) |
|
|
175
|
+
| A one-line behavioural setting a space admin may change from chat (`language`, `timezone`) | preference | `AGENTS.md` (would need a deploy to change) |
|
|
176
|
+
| Voice that must hold across all spaces of one deployment | Bot Character | every space's `AGENTS.md` (drifts) |
|
|
177
|
+
| Deterministic business logic, credentials, anything with numbers or dates | a capability / engine / extension, returning structured facts | prompt prose ("compute the day name yourself") |
|
|
178
|
+
| What members may do | `role.member.permissions` / applicative `member_permissions` | prompt prose ("only admins may…") — the model is not the enforcement |
|
|
179
|
+
| Knobs an extension reads (`feed-watch.*`, `longview.*`) | `extension_config` in the space profile (repo-owned, drift-checked) | hand edits on the box |
|
|
180
|
+
| A fact the bot keeps getting wrong | a file the bot reads each turn (`MEMORY.md`, a notebook under `knowledge/`), written with source and date | a longer rule |
|
|
181
|
+
|
|
182
|
+
One rule in exactly one layer. A rule repeated "for emphasis" is the next
|
|
183
|
+
contradiction — and when you move a rule into `AGENTS.md`, delete the
|
|
184
|
+
preference it came from (`remove_preferences:` in a space profile exists for
|
|
185
|
+
this).
|
|
186
|
+
|
|
187
|
+
## 7. Reading the live layers
|
|
188
|
+
|
|
189
|
+
```bash
|
|
190
|
+
# Everything the football space receives, without touching it
|
|
191
|
+
bun scripts/space-profile.ts dump --project ~/whatsapp-bot --space football-friends
|
|
192
|
+
|
|
193
|
+
# Drift between the repo profile and the live space
|
|
194
|
+
bun scripts/space-profile.ts check --project ~/whatsapp-bot --profile examples/profiles/football-reporter
|
|
195
|
+
|
|
196
|
+
# The exact prompt a run received (requires agent.trace_runs: true + image rebuild)
|
|
197
|
+
ls .mercury/traces/ # <container-name>.jsonl, 7-day TTL
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
`agent.trace_runs` is off by default and needs the image rebuilt when
|
|
201
|
+
toggled. With it off, "what did the model actually see and open?" is
|
|
202
|
+
unanswerable after the fact — turn it on for a bounded window whenever you
|
|
203
|
+
are tuning a profile. A trace holds the full prompt and reply in clear text;
|
|
204
|
+
treat it like debug logging.
|
package/docs/extensions.md
CHANGED
|
@@ -121,6 +121,8 @@ The directory must contain a `SKILL.md` file in pi's [skill format](https://agen
|
|
|
121
121
|
|
|
122
122
|
Skills can contain multiple files — scripts, references, assets — not just SKILL.md. The agent uses relative paths from SKILL.md to access them.
|
|
123
123
|
|
|
124
|
+
Only the `name`, `description` and path of each skill reach the system prompt; the agent reads the body on demand when the description matches. How to write a description that fires, where space-local skills must live (`.mercury/spaces/<space>/.pi/skills/`), and how to make a profile actually use its skills: [skills-guide.md](skills-guide.md).
|
|
125
|
+
|
|
124
126
|
### `mercury.requires(capabilities)`
|
|
125
127
|
|
|
126
128
|
Declare that this extension's skill (or CLI workflows) needs certain model capabilities (`tools`, `vision`, etc.). If **no** leg in `MERCURY_MODEL_CHAIN` satisfies **all** listed flags, the extension skill is not copied into the global skills directory and Mercury logs a startup warning.
|