RAPP agent.py to Agent Skill — and back. The same pair works unchanged in
Copilot Studio, Cowork, Scout, and other SKILL.md-reading harnesses, giving
each of them RAPP agent.py compatibility. The Rapid Agent
Prototype Pattern: a capability is one Python file — one class, one typed
metadata contract, one perform() method — and every other shape is a
projection of it. This skill converts between the two shapes with zero
fidelity loss:
- agent — a RAPP single-file agent cartridge (
*_agent.py). The canonical
form.
- skill — an Agent Skill projection shipped as a pair: a
SKILL.md
with the full Python embedded (plus an rci-capsule:v1: comment vaulting the
byte-exact original, sha256-verified) and a linked python file beside it
that literally is the agent.py. A host with sandbox execution — Copilot
Studio becomes a first-party user of agent.py this way — runs the linked
file directly; the SKILL.md alone remains self-sufficient if the linked file
is missing. Converting back is a checksum-verified restore, never a
re-render.
Everything routes through one deterministic engine. Do not improvise
conversions, do not hand-edit formats, and do not paraphrase code — model-driven
transformation is exactly the drift this skill exists to prevent.
Commands
Run from this skill's directory. Stdlib-only Python 3.9+, fully offline — no
pip install, no network, no credentials.
python3 scripts/toast.py convert <path> --to skill -o out/SKILL.md # agent.py -> SKILL.md + linked agent
python3 scripts/toast.py convert <path> --to agent # SKILL.md -> agent.py
python3 scripts/toast.py roundtrip <path> # prove fidelity, exit 1 on drift
python3 scripts/toast.py inspect <path> # capsule status, identity, provenance
python3 scripts/toast.py selftest # prove every verdict can fire
Always pass -o with a path that is not an existing file you care about; the
tool refuses to overwrite its own source file or an existing target with
different bytes without --force. A byte-identical existing target is an
idempotent success. Never target this skill's own SKILL.md. Without -o,
output lands next to the source file (the tool prints the absolute path).
Exit codes: 0 = verified, 1 = drift or refusal (message says which), 2 =
RAW BREAD — a capsule-less SKILL.md has no byte-exact return trip yet;
convert it to an agent first, or pass --allow-raw to measure
capability-level fidelity only. Treat only exit 1 as drift.
The full lifecycle: the FIRST conversion of a hand-written SKILL.md creates a
runnable launchpad agent without inventing behavior. Instructions travel
verbatim; an explicit ## Parameters JSON-Schema fence supplies the typed
contract; a Python fence whose info string is
python # rapp:deterministic supplies implementation when present. Ordinary
example fences remain documentation. A prose-only skill remains prose-only in
the launchpad. Converting
that agent back embeds it literally inside a new SKILL.md — single-file
shareable — with the agent.py linked beside it, and it still maps back to the
identical agent.py. Both platforms are served by the same pair, and the Python
is preserved byte-exact at every hop.
Converting agent.py → Agent Skill
- Run
convert <file> --to skill -o <dir>/SKILL.md. Two things are emitted:
the SKILL.md (frontmatter from the agent's own metadata, its docstring as
instructions, a generated ## Parameters JSON-Schema fence, a generated
## Run this — do not improvise section with the entire agent.py
embedded verbatim, and the capsule comment) plus the linked agent
file next to it — a byte-exact copy of the source. Ship both in the
skill's bundle.
- Immediately run
roundtrip <file> on the source agent. Report success only
on IDENTICAL. On DRIFT, report the two sha256 prefixes it prints and
stop — never hand-patch the output to make it match.
- The output says
SYNTHESISED (fresh projection) or RESTORED (byte-exact)
(a vaulted original existed). Relay that word to the user — the two must
never be confused.
Converting SKILL.md → agent.py
- Run
convert <file> --to agent.
- If the SKILL.md carries a capsule, the agent is restored byte-exact
(sha256-verified; a checksum mismatch aborts — never bypass it).
- If it is a plain hand-written SKILL.md (no capsule), a launchpad agent is
synthesised: instructions travel verbatim in
INSTRUCTIONS, typed
parameters come from a ## Parameters fence when present, and a fence
whose info string is python # rapp:deterministic is preserved as
implementation when present. Ordinary Python examples are never
executable. Otherwise
perform() returns the original instructions plus the supplied inputs;
it does not infer commands from prose. Say so explicitly — a synthesis is
a capability projection, not a restoration. A prose-only skill (no
Parameters fence) synthesises an agent with an EMPTY parameter schema —
the contract is untyped and nothing is validatable as required; tell the
user so, and offer to add a ## Parameters JSON-Schema fence to the source
skill first if they want a typed contract.
- The emitted filename ends
_agent.py (snake_case) so RAPP Brainstem
auto-discovery loads it unchanged. Contract details:
references/rapp-agent-contract.md.
Verifying (mandatory before claiming success)
roundtrip on an agent proves: agent → skill → agent returns the exact
original bytes, and the projection is a fixed point over repeated cycles.
roundtrip on a converted SKILL.md proves: the vaulted agent restores
checksum-verified, and the inline Python fence still matches it — editing
inside the generated markers is detected as INLINE DRIFT, exit 1.
- Behavioural fidelity is graded, never assumed: EXEC (host executed the
file — only claim after
python3 <file> --tool actually exits 0), CODE
(the code travels in the fence), SPEC (typed contract only). Never report
EXEC without having executed.
- Try it end to end on the bundled sample:
python3 scripts/toast.py roundtrip assets/hello_rapp_agent.py
Host tiers for the emitted Agent Skill
- Copilot Studio / Cowork (sandbox execution): run the linked agent file
directly —
--tool for the contract, one JSON object for arguments; if the
linked file is missing, materialize it verbatim from the fence first. Treat
stdout as a tool result: collect missing inputs, execute returned steps in
order, follow returned instructions, or otherwise use the result verbatim.
This earns the EXEC tier and makes the host a first-party user of the
agent.py itself.
- Scout and other instruction-driven hosts (no sanctioned script execution
today): the same SKILL.md still works — treat the Parameters schema and the
fenced code as the exact specification and never paraphrase a step (CODE
tier). When the host later gains a sanctioned execution path, the identical
file upgrades to EXEC. The file does not change — that is the promotion, not
a port.
Talking to a live RAPP entity
When a running RAPP brainstem is available, everything rides one wire: POST /chat. Follow references/rapp1-protocol.md
exactly — the response field is response (never assistant_response), keep
the returned session_id for continuity, and never invent sibling REST
routes. Dropping a converted *_agent.py into the brainstem's agents/
directory hot-loads it with no restart.
Guardrails
- Never edit content between
<!-- toaster:generated:begin --> and
<!-- toaster:generated:end -->, and never strip or truncate an
rci-capsule:v1: comment — that is the byte-exact original.
- Never import or execute an agent file in order to read it; the converter
parses with
ast only. Executing the agent is a separate, user-visible step.
- Report unconvertible files with the reason; never silently skip or "fix" them.
- Sandbox files do not persist across conversations: return or save the
converted artifacts in the same turn you produce them.
- The converter carries identity through; it never mints identity from content.
1---2name: rapp-agent-converter3description: Use this skill whenever the user works with RAPP single-file agents (the Rapid Agent Prototype Pattern): converting an agent.py cartridge into a Copilot Studio / Cowork / Scout Agent Skill, converting a SKILL.md back into a runnable agent.py, bringing a RAPP-built agent into Copilot Studio, verifying such a conversion lost nothing, or talking to a live RAPP brainstem over its /chat endpoint. Always run the bundled deterministic converter instead of transforming the files by hand.4---56RAPP `agent.py` to Agent Skill — and back. The same pair works unchanged in7Copilot Studio, Cowork, Scout, and other SKILL.md-reading harnesses, giving8each of them RAPP agent.py compatibility. The Rapid Agent9Prototype Pattern: a capability is **one Python file** — one class, one typed10`metadata` contract, one `perform()` method — and every other shape is a11projection of it. This skill converts between the two shapes with zero12fidelity loss:1314- **agent** — a RAPP single-file agent cartridge (`*_agent.py`). The canonical15 form.16- **skill** — an Agent Skill projection shipped as a **pair**: a `SKILL.md`17 with the full Python embedded (plus an `rci-capsule:v1:` comment vaulting the18 byte-exact original, sha256-verified) and a **linked python file beside it19 that literally is the agent.py**. A host with sandbox execution — Copilot20 Studio becomes a first-party user of agent.py this way — runs the linked21 file directly; the SKILL.md alone remains self-sufficient if the linked file22 is missing. Converting back is a checksum-verified restore, never a23 re-render.2425Everything routes through one deterministic engine. Do not improvise26conversions, do not hand-edit formats, and do not paraphrase code — model-driven27transformation is exactly the drift this skill exists to prevent.2829## Commands3031Run from this skill's directory. Stdlib-only Python 3.9+, fully offline — no32pip install, no network, no credentials.3334```bash35python3 scripts/toast.py convert <path> --to skill -o out/SKILL.md # agent.py -> SKILL.md + linked agent36python3 scripts/toast.py convert <path> --to agent # SKILL.md -> agent.py37python3 scripts/toast.py roundtrip <path> # prove fidelity, exit 1 on drift38python3 scripts/toast.py inspect <path> # capsule status, identity, provenance39python3 scripts/toast.py selftest # prove every verdict can fire40```4142Always pass `-o` with a path that is not an existing file you care about; the43tool refuses to overwrite its own source file or an existing target with44different bytes without `--force`. A byte-identical existing target is an45idempotent success. Never target this skill's own `SKILL.md`. Without `-o`,46output lands next to the source file (the tool prints the absolute path).4748Exit codes: 0 = verified, 1 = drift or refusal (message says which), 2 =49`RAW BREAD` — a capsule-less SKILL.md has no byte-exact return trip yet;50convert it to an agent first, or pass `--allow-raw` to measure51capability-level fidelity only. Treat only exit 1 as drift.5253The full lifecycle: the FIRST conversion of a hand-written SKILL.md creates a54runnable launchpad agent without inventing behavior. Instructions travel55verbatim; an explicit `## Parameters` JSON-Schema fence supplies the typed56contract; a Python fence whose info string is57`python # rapp:deterministic` supplies implementation when present. Ordinary58example fences remain documentation. A prose-only skill remains prose-only in59the launchpad. Converting60that agent back embeds it literally inside a new SKILL.md — single-file61shareable — with the agent.py linked beside it, and it still maps back to the62identical agent.py. Both platforms are served by the same pair, and the Python63is preserved byte-exact at every hop.6465## Converting agent.py → Agent Skill66671. Run `convert <file> --to skill -o <dir>/SKILL.md`. Two things are emitted:68 the SKILL.md (frontmatter from the agent's own metadata, its docstring as69 instructions, a generated `## Parameters` JSON-Schema fence, a generated70 `## Run this — do not improvise` section with the **entire agent.py71 embedded verbatim**, and the capsule comment) plus the **linked agent72 file** next to it — a byte-exact copy of the source. Ship both in the73 skill's bundle.742. Immediately run `roundtrip <file>` on the source agent. Report success only75 on `IDENTICAL`. On `DRIFT`, report the two sha256 prefixes it prints and76 stop — never hand-patch the output to make it match.773. The output says `SYNTHESISED` (fresh projection) or `RESTORED (byte-exact)`78 (a vaulted original existed). Relay that word to the user — the two must79 never be confused.8081## Converting SKILL.md → agent.py82831. Run `convert <file> --to agent`.84 - If the SKILL.md carries a capsule, the agent is **restored byte-exact**85 (sha256-verified; a checksum mismatch aborts — never bypass it).86 - If it is a plain hand-written SKILL.md (no capsule), a launchpad agent is87 **synthesised**: instructions travel verbatim in `INSTRUCTIONS`, typed88 parameters come from a `## Parameters` fence when present, and a fence89 whose info string is `python # rapp:deterministic` is preserved as90 implementation when present. Ordinary Python examples are never91 executable. Otherwise92 `perform()` returns the original instructions plus the supplied inputs;93 it does not infer commands from prose. Say so explicitly — a synthesis is94 a capability projection, not a restoration. A prose-only skill (no95 Parameters fence) synthesises an agent with an EMPTY parameter schema —96 the contract is untyped and nothing is validatable as required; tell the97 user so, and offer to add a `## Parameters` JSON-Schema fence to the source98 skill first if they want a typed contract.992. The emitted filename ends `_agent.py` (snake_case) so RAPP Brainstem100 auto-discovery loads it unchanged. Contract details:101 [references/rapp-agent-contract.md](references/rapp-agent-contract.md).102103## Verifying (mandatory before claiming success)104105- `roundtrip` on an agent proves: agent → skill → agent returns the exact106 original bytes, and the projection is a fixed point over repeated cycles.107- `roundtrip` on a converted SKILL.md proves: the vaulted agent restores108 checksum-verified, and the inline Python fence still matches it — editing109 inside the generated markers is detected as INLINE DRIFT, exit 1.110- Behavioural fidelity is graded, never assumed: **EXEC** (host executed the111 file — only claim after `python3 <file> --tool` actually exits 0), **CODE**112 (the code travels in the fence), **SPEC** (typed contract only). Never report113 EXEC without having executed.114- Try it end to end on the bundled sample:115 `python3 scripts/toast.py roundtrip assets/hello_rapp_agent.py`116117## Host tiers for the emitted Agent Skill118119- **Copilot Studio / Cowork** (sandbox execution): run the linked agent file120 directly — `--tool` for the contract, one JSON object for arguments; if the121 linked file is missing, materialize it verbatim from the fence first. Treat122 stdout as a tool result: collect missing inputs, execute returned `steps` in123 order, follow returned `instructions`, or otherwise use the result verbatim.124 This earns the EXEC tier and makes the host a first-party user of the125 agent.py itself.126- **Scout** and other instruction-driven hosts (no sanctioned script execution127 today): the same SKILL.md still works — treat the Parameters schema and the128 fenced code as the exact specification and never paraphrase a step (CODE129 tier). When the host later gains a sanctioned execution path, the identical130 file upgrades to EXEC. The file does not change — that is the promotion, not131 a port.132133## Talking to a live RAPP entity134135When a running RAPP brainstem is available, everything rides one wire: `POST136/chat`. Follow [references/rapp1-protocol.md](references/rapp1-protocol.md)137exactly — the response field is `response` (never `assistant_response`), keep138the returned `session_id` for continuity, and never invent sibling REST139routes. Dropping a converted `*_agent.py` into the brainstem's `agents/`140directory hot-loads it with no restart.141142## Guardrails143144- Never edit content between `<!-- toaster:generated:begin -->` and145 `<!-- toaster:generated:end -->`, and never strip or truncate an146 `rci-capsule:v1:` comment — that is the byte-exact original.147- Never import or execute an agent file in order to read it; the converter148 parses with `ast` only. Executing the agent is a separate, user-visible step.149- Report unconvertible files with the reason; never silently skip or "fix" them.150- Sandbox files do not persist across conversations: return or save the151 converted artifacts in the same turn you produce them.152- The converter carries identity through; it never mints identity from content.