@muretai/agent-entry 1.9.0 → 1.11.0
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 +164 -39
- package/conformance/receptor-check.mjs +904 -0
- package/diagrams/become.png +0 -0
- package/diagrams/desk.svg +17 -0
- package/diagrams/x402.svg +21 -0
- package/examples/server.mjs +8 -0
- package/muretai-agent-entry.mjs +323 -88
- package/package.json +8 -3
- package/scripts/distill/README.md +32 -0
- package/scripts/distill/distill.mjs +51 -0
- package/scripts/distill/fixtures.json +10 -0
- package/scripts/distill/lib.mjs +100 -0
- package/scripts/distill/loop.mjs +46 -0
- package/scripts/distill/measure.mjs +80 -0
- package/scripts/distill/record.mjs +90 -0
- package/scripts/distill/test.mjs +43 -0
- package/spec/skill-distill.md +219 -0
- package/spec/v1.md +20 -0
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
# Agent Entry — Episode-to-Skill (site side)
|
|
2
|
+
|
|
3
|
+
Status: **local loop shipped** (`scripts/distill/`). Does not change the v1
|
|
4
|
+
HTTP contract (`spec/v1.md`).
|
|
5
|
+
Method: Repo-To-Skill (arXiv 2609.02749) — distill, verify, load only what
|
|
6
|
+
the task needs. Source: outcome-labeled knocks at **this** door, not a
|
|
7
|
+
GitHub crawl and not a network-wide catalog.
|
|
8
|
+
|
|
9
|
+
This repository stays the door. Distillation is an **owner-side, offline**
|
|
10
|
+
loop. Nothing here is added to `muretai-agent-entry.mjs` at request time.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## 1. What is missing today
|
|
15
|
+
|
|
16
|
+
A visiting agent reads the card before it knocks. If `skills[]` is empty or
|
|
17
|
+
wrong, it guesses and learns the menu from refusals. The README already
|
|
18
|
+
states the two owner duties:
|
|
19
|
+
|
|
20
|
+
- every `examples[]` entry must be answerable by the responder
|
|
21
|
+
- declare only what the responder actually does
|
|
22
|
+
|
|
23
|
+
Those duties are still hand-written. The paper's claim is that this
|
|
24
|
+
operating knowledge already exists in **grounded outcomes** — signed
|
|
25
|
+
envelopes plus what the door did — and can be distilled into the menu the
|
|
26
|
+
next visitor sees.
|
|
27
|
+
|
|
28
|
+
The door already emits the labels, without changing a verdict:
|
|
29
|
+
|
|
30
|
+
- `observer(env)` runs **after** the reply; its return is discarded
|
|
31
|
+
- `stats()` / `clientStats()` count family and stage, including refusals
|
|
32
|
+
- JSON-RPC refusals teach (`-32004` over-rate, unsigned, replay, wrong
|
|
33
|
+
recipient); the recipe already rides in the refusal
|
|
34
|
+
- the responder's own result (answered / asked for a missing field /
|
|
35
|
+
handed off) is the site-specific outcome
|
|
36
|
+
|
|
37
|
+
User-Agent never affects `verified`, a ledger row, a rate lane, or any
|
|
38
|
+
refusal. Distillation must not reopen that. UA is a counting hint, not a
|
|
39
|
+
training label for "who to trust".
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## 2. What to steal, what to refuse
|
|
44
|
+
|
|
45
|
+
Steal: four-stage distillation (scope → ground → construct → verify);
|
|
46
|
+
skills as operating context, not a new control loop; environment-grounded
|
|
47
|
+
admission (a transcript-only gate cannot improve uniformly); withhold-the-
|
|
48
|
+
skill measurement.
|
|
49
|
+
|
|
50
|
+
Refuse:
|
|
51
|
+
|
|
52
|
+
- Distiller inside the one-file runtime (zero dependencies, no database)
|
|
53
|
+
- a hosted catalog of every site's skills
|
|
54
|
+
- FOLLOW of visitor-authored text (`env.text` stays untrusted data)
|
|
55
|
+
- stamping a third-party `howToUrl` (empty means omitted; only a URL the
|
|
56
|
+
owner operates)
|
|
57
|
+
- changing any wire byte or verdict because a skill exists
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## 3. Mapping
|
|
62
|
+
|
|
63
|
+
| Paper | This repo |
|
|
64
|
+
|---|---|
|
|
65
|
+
| Declarative source | Signed inbound `text` + door outcome (verify / refuse code / responder result) |
|
|
66
|
+
| Skill | A2A `skills[]` on the **signed** card; optional owner `howToUrl`; optional `SKILL.md` the owner hosts |
|
|
67
|
+
| Skill graph | One entry skill (what this door answers) → component skills per declared capability |
|
|
68
|
+
| Router | The card itself. Visitors read `skills[]` before POST. Agent Web Router finds the door; it does not write this menu |
|
|
69
|
+
| Verification | Card signature still covers the menu. Examples are driven through the responder in tests (already required) |
|
|
70
|
+
| Creator / researcher | Owner Distiller writes a proposed menu; the running entry only **serves** what the owner published |
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
visitor --probe--> card.skills[] (menu; signed)
|
|
74
|
+
visitor --knock--> POST door (unchanged contract)
|
|
75
|
+
observer --trace--> local log (after verdict)
|
|
76
|
+
Distiller (offline) --> proposed skills[] / how-to
|
|
77
|
+
owner publishes --> card resigns
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## 4. Distiller pipeline (offline, this repo or a sibling package)
|
|
83
|
+
|
|
84
|
+
Anchor is this origin's door, not a task on the open web.
|
|
85
|
+
|
|
86
|
+
1. **Scope.** One capability the responder already implements (hours,
|
|
87
|
+
quote, book, …). Do not invent a skill the responder cannot keep.
|
|
88
|
+
2. **Ground.** Read owner-local traces only: `observer` rows the owner
|
|
89
|
+
chose to keep, plus the door's refuse reason. A row is
|
|
90
|
+
`{text, verified, refuse_code?, responder_tag, ts}`. No operator
|
|
91
|
+
aggregation across sites.
|
|
92
|
+
3. **Construct.** Propose:
|
|
93
|
+
- `skills[]` id / name / description / tags / **answerable** examples
|
|
94
|
+
- optional how-to prose at a URL the owner operates
|
|
95
|
+
- construction record `R`: evidence (trace ids), checks, remaining gaps
|
|
96
|
+
4. **Verify (M0).** Before publish:
|
|
97
|
+
- the new card still signs
|
|
98
|
+
- every example POSTed to the local entry gets a signed reply the
|
|
99
|
+
visitor could accept (existing "examples are promises" rule)
|
|
100
|
+
- refuse rate on a frozen visitor suite does not rise
|
|
101
|
+
- remaining gaps stay in `R`
|
|
102
|
+
|
|
103
|
+
The running entry never imports the Distiller. Shipped layout (not
|
|
104
|
+
imported by the one-file runtime):
|
|
105
|
+
|
|
106
|
+
```
|
|
107
|
+
scripts/distill/ # owner CLI
|
|
108
|
+
record.mjs # fileSink() for observer → var/traces.jsonl
|
|
109
|
+
distill.mjs # traces → generated/skills.json
|
|
110
|
+
measure.mjs # M2 with/without the proposed menu
|
|
111
|
+
loop.mjs # distill → measure → mutation
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
`npm run distill`. Proposed `skills[]` is never written onto the running
|
|
115
|
+
card. `--m0` also runs the door conformance suite.
|
|
116
|
+
|
|
117
|
+
`createAgentEntry({ observer })` already exists. Recording is an owner
|
|
118
|
+
choice. Default remains no disk.
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## 5. Measurement
|
|
123
|
+
|
|
124
|
+
A skill cannot be graded by reading it (ACES, arXiv 2608.20614).
|
|
125
|
+
|
|
126
|
+
- **M0 admission** — signed card; examples answerable; contract suite
|
|
127
|
+
(`conformance/`) still green. Fail-closed.
|
|
128
|
+
- **M2 lift** — freeze responder, rates, and a held-out visitor prompt
|
|
129
|
+
set. Arm A: current `skills[]` / how-to. Arm B: proposed menu. Score
|
|
130
|
+
only what a visitor observes: first-knock useful answer, refuse-for-
|
|
131
|
+
missing-field, handoff that the card still names. Not token count.
|
|
132
|
+
- **Producer mutation** — Distiller emits empty `skills[]`. Lift must
|
|
133
|
+
fall to ~0. If it stays green, the test was scoring the responder.
|
|
134
|
+
- **No leaderboard.** One site, that site's traces, that site's reader.
|
|
135
|
+
|
|
136
|
+
Publish rule: M0 holds, M2 first-knock success rises or refuse-for-guess
|
|
137
|
+
falls, mutation kills the lift.
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
## 6. First dojo (this repo, no production traffic)
|
|
142
|
+
|
|
143
|
+
Frozen visitor prompts against `examples/server.mjs` (or a fixture
|
|
144
|
+
responder) that requires a missing field the naive visitor omits.
|
|
145
|
+
|
|
146
|
+
- Train traces: naive knocks that the responder rejects with a teachable
|
|
147
|
+
reason, plus one complete knock.
|
|
148
|
+
- Distiller writes a skill example that includes the field.
|
|
149
|
+
- Holdout: a new wording of the same need.
|
|
150
|
+
- Naive visitor still omits the field; skill-equipped visitor includes it.
|
|
151
|
+
- Mutation: empty Distiller, both arms omit, lift 0.
|
|
152
|
+
|
|
153
|
+
Do not use live `muretai.com` traffic for the first number.
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## 7. What this does not change
|
|
158
|
+
|
|
159
|
+
v1 HTTP surface, Ed25519 envelope, account-from-first-signature, rate
|
|
160
|
+
lanes, Web Bot Auth as recognition-only, `Link` signpost, path mounts,
|
|
161
|
+
`domains`. Agent Web Router remains a **visitor** of this door. It may
|
|
162
|
+
read the distilled menu; it must not write it.
|
|
163
|
+
|
|
164
|
+
## 8. Relation to `muretai-skill-distill`
|
|
165
|
+
|
|
166
|
+
That sibling app proved withhold-the-skill lift on a fail-closed parse
|
|
167
|
+
dojo. This design is the same method with a different source: **door
|
|
168
|
+
outcomes**, not `x-rlds` lines. Do not vendor-copy core crypto. The entry
|
|
169
|
+
already verifies signatures.
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## 9. Live loop — two rails (we never see installer traffic)
|
|
174
|
+
|
|
175
|
+
This package is installed by other people, on origins we do not operate.
|
|
176
|
+
Their visitors' messages, accounts, and `observer` rows are **not ours**
|
|
177
|
+
and MUST NOT be fetched, phoned home, or scraped. There is no telemetry
|
|
178
|
+
channel. Evolution therefore splits.
|
|
179
|
+
|
|
180
|
+
### Rail A — this package (what we can update)
|
|
181
|
+
|
|
182
|
+
We improve the **door machinery and the refusal recipe**, not a site's
|
|
183
|
+
menu. Labels come only from sources we already own or that someone
|
|
184
|
+
chose to publish:
|
|
185
|
+
|
|
186
|
+
- `conformance/` vectors and the contract suite (attacks we author)
|
|
187
|
+
- the doors **we** run (for example the muretai.com entry)
|
|
188
|
+
- a GitHub issue a site owner **opts into**, attaching a redacted
|
|
189
|
+
fixture they exported (`export --redact` if later built; default off,
|
|
190
|
+
never runs itself)
|
|
191
|
+
|
|
192
|
+
A package release may change refusal text, `howTo` defaults (still no
|
|
193
|
+
third-party host), rate-lane behaviour, or new contract tests. It MUST
|
|
194
|
+
NOT patch a stranger's `skills[]`. That list is their signed claim.
|
|
195
|
+
|
|
196
|
+
Measure a release against **our** fixtures (§5). If we do not have a
|
|
197
|
+
new fixture, we do not have a new skill.
|
|
198
|
+
|
|
199
|
+
### Rail B — each installer's machine (what they can update)
|
|
200
|
+
|
|
201
|
+
The only place their knock data exists is their process. The Distiller,
|
|
202
|
+
if they run it, reads a local `observer` sink they configured. The
|
|
203
|
+
child `skills[]` stays on their card. We never receive it.
|
|
204
|
+
|
|
205
|
+
```
|
|
206
|
+
their observer → their disk → their Distiller → their next card
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
`stats()` they already have is for **them**. It is not a feed to us.
|
|
210
|
+
User-Agent remains unusable as a label.
|
|
211
|
+
|
|
212
|
+
### What we do when we cannot see production
|
|
213
|
+
|
|
214
|
+
We do not wait for it. The first dojo (§6) and every later package
|
|
215
|
+
change are fixture-grown. When a user reports "visitors keep getting
|
|
216
|
+
refused and the recipe did not teach X", the artifact we want is a
|
|
217
|
+
**reproducing envelope**, not their ledger. That becomes a conformance
|
|
218
|
+
case. That is the only upstream ratchet that does not take their
|
|
219
|
+
customers.
|
package/spec/v1.md
CHANGED
|
@@ -396,6 +396,25 @@ higher rate than the signed lane's aggregate.
|
|
|
396
396
|
> **Observation.** With the lane on, drive unsigned requests above the bound; assert refusal. An
|
|
397
397
|
> unauthenticated caller must never become an unmetered signing oracle.
|
|
398
398
|
|
|
399
|
+
**AE-30.** An entry **MAY** publish `agentEntry.prefer`: the site's own order of its ways in
|
|
400
|
+
for a visiting agent. It is an array whose entries are a kind — `"page"`, `"card"`, `"mcp"` —
|
|
401
|
+
or an object `{"kind": <kind>, "when": <condition>}` with `when` one of `person`, `alone`,
|
|
402
|
+
`key`, `no-key`, `token`, `browser`, read by the visitor against what it has on hand. When
|
|
403
|
+
published it **MUST** appear under the neutral `agentEntry` key exactly as the operator
|
|
404
|
+
declared it (validated, not rewritten), and **MUST** appear identically in the signed
|
|
405
|
+
envelope's inner card. The legacy `muretai` alias **MUST NOT** carry it. When not configured,
|
|
406
|
+
the card **MUST NOT** carry a `prefer` key. A declaration that fails validation **MUST** make
|
|
407
|
+
the entry refuse to start rather than publish a corrected or partial order.
|
|
408
|
+
|
|
409
|
+
> **Observation.** Start an entry with a declaration; `GET` the card and the envelope; assert
|
|
410
|
+
> `agentEntry.prefer` equals the declaration in both and `muretai` has no `prefer`. Start one
|
|
411
|
+
> without; assert no `prefer` key. Start one with `["teleport"]`; assert it exits non-zero and
|
|
412
|
+
> binds nothing. Why refuse rather than fix: a signed card is the origin's statement, and a
|
|
413
|
+
> statement the operator did not make is a worse card than none — the same posture as a bad
|
|
414
|
+
> `domains` list. Why the visitor's conditions live here: which way in a stranger should try
|
|
415
|
+
> first is the site's design (read on the page, become a counterparty later — or knock first),
|
|
416
|
+
> and the card is the one place the site can say so that a page script cannot rewrite.
|
|
417
|
+
|
|
399
418
|
---
|
|
400
419
|
|
|
401
420
|
## 5. Relationship to other specifications
|
|
@@ -629,6 +648,7 @@ be written is a requirement that does not belong in §4.
|
|
|
629
648
|
| AE-27 | MUST | size caps | oversized body and text |
|
|
630
649
|
| AE-28 | MUST | aggregate reply ceiling, refused with `-32004` | drive above the ceiling |
|
|
631
650
|
| AE-29 | MUST | unsigned lane bounded entry-wide | drive the anonymous lane |
|
|
651
|
+
| AE-30 | MAY / MUST | `agentEntry.prefer` verbatim on card + envelope, or absent; invalid refuses to start | `GET` both, compare; start with a bad list → exit ≠ 0 |
|
|
632
652
|
|
|
633
653
|
---
|
|
634
654
|
|