Agent Provenance: MCP, Skills, and Hooks
The three layers that carry 4Quays signing across agent platforms — and which one actually guarantees every message is signed.
An agent integration crosses three extension layers. They look interchangeable but differ in what invokes them, and that difference decides what each can promise. Ask each layer to do only what it can guarantee.
The three layers
| Layer | Invoked by | Guarantee | Give it |
|---|---|---|---|
| MCP | the model deciding to call a tool | best-effort | sign / verify / encrypt_for / decrypt as native tools, with the API key in the client's config (never in the chat) |
| Skill | relevance matching against its description | best-effort | judgement — read the verify gate, decide whether to trust an inbound signature, when to sign a commitment, when to encrypt |
| Hooks | the event itself (a prompt was submitted; a turn ended) | unconditional | signing every prompt and response, recorded to a local journal |
Only the hook fires without the model choosing to. A skill that says "sign every message" still won't run on a bare Hello? — there's nothing to match against. MCP and skills are the wrong place for an every-message promise; a per-turn hook is the only place it holds.
What to ship
- MCP server — one artifact reaches every surveyed client. Published as
@4quays/mcp. Highest leverage: it also keeps the key out of shell commands and conversations. - Skill — one portable
SKILL.md(open standard) scoped to judgement, not obligation. Ships from the agent's Skill tab; drop it in.agents/skills/4quays-signing/or upload it to a host that accepts skill files. - Hook packs — per vendor, because event names and config formats don't converge.
@4quays/agent-hooksships one portable script plus a config per host (Claude Code, Codex, Cursor, Gemini CLI). It signs each turn and appends the block to.4quays/journal.jsonl.
Be precise about "every message"
The every-message guarantee holds only on hosts that expose a per-turn hook — the agent CLIs and IDEs above. On surfaces with no per-turn code execution, notably ChatGPT, signing every message is not achievable at any privilege level; the honest offer there is a model-invoked MCP tool (signs when the model decides to). Don't market a guarantee the mechanism can't deliver.
Surfaces that can't hook: hash-chain mode
Where per-turn signing is impossible, a periodically-signed hash chain over the transcript still delivers tamper-evidence (each entry chained over the prior, so reordering or deletion is detectable) — at a fraction of the per-message cost. This is a planned mode for the journal; the shipped default is one signed block per turn.