# Sponsio

> Install, observe, tune, and enforce Sponsio: a runtime contract layer for LLM agents that blocks unsafe tool calls and scores output quality against declared rules. Use when the user wants to set up / add / install Sponsio, add guardrails or runtime safety to an LLM agent, generate or refine a sponsio.yaml, audit tool configurations for risks (data leaks, unguarded writes, missing confirmations),…

- **Type:** Skill
- **Install:** `agentstack add skill-sponsiolabs-sponsio-sponsio`
- **Verified:** Pending review
- **Seller:** [SponsioLabs](https://agentstack.voostack.com/s/sponsiolabs)
- **Installs:** 0
- **Category:** [AI & ML](https://agentstack.voostack.com/c/ai-and-ml)
- **Latest version:** 0.1.0
- **License:** Apache-2.0
- **Upstream author:** [SponsioLabs](https://github.com/SponsioLabs)
- **Source:** https://github.com/SponsioLabs/Sponsio/tree/main/sponsio/skills/sponsio
- **Website:** https://sponsio.dev/

## Install

```sh
agentstack add skill-sponsiolabs-sponsio-sponsio
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Sponsio — Agent Safety Lifecycle Companion

Sponsio is a Python/TypeScript runtime safety layer for LLM agents: it evaluates deterministic contracts against each tool call and can block (enforce) or just log (observe) violations. The engine is deterministic-only. This skill covers the full lifecycle — first-time setup, contract authoring/review, observe-mode tuning, and flipping to enforce — by orchestrating Sponsio's CLI and explaining its output in plain language.

This skill does NOT reimplement Sponsio's logic; it calls the CLI and interprets results.

## When to use this skill

Dispatch by what the user is trying to do. Pick ONE workflow and follow it; do not run multiple workflows in one turn.

| User is… | → Workflow |
|---|---|
| Setting up Sponsio for the first time in a project ("add sponsio", "install sponsio", "add guardrails") | **W1 — Initial setup** (just dispatch ``sponsio init``) |
| Handing you a codebase and asking "what could go wrong?" / wants a fresh contract file from scratch / has a policy doc to encode | **W2 — Audit & refine** |
| Authoring contracts for a Claude Code / OpenClaw plugin or a bare MCP server (input is a plugin manifest, not source code) | **W2b — Plugin / MCP contracts** |
| Tightening rules that apply to Task-spawned subagents (Cursor / Claude Code) — they lack user context and need stricter privileges than the main agent | **W2c — Subagent privilege boundary** |
| Tuning the IDE's OWN host-plugin library (Claude Code's Bash / Read / Write / MCP gating; Cursor likewise) — different from the user's project sponsio.yaml | hand off to the ``sponsio-claude-code:configure`` skill (or the cursor analog).  Don't reimplement here. |
| Has Sponsio running in observe mode and wants to review violations, tune thresholds, silence false positives | **W3 — Tune in observe** |
| Ready to ship — wants to move from observe to enforce, needs regression confidence | **W4 — Flip to enforce** |
| Sponsio errored, a rule isn't firing when it should, a rule is firing when it shouldn't | **W5 — Troubleshoot** |

Do NOT trigger for: general LLM-safety discussions not tied to a specific codebase; non-agent code review (linting, correctness).

## Prerequisites (run silently before any workflow)

```bash
sponsio --version
```

- Not found → install: `pip install sponsio` (or `pip install -e ".[all]"` from a local clone).
- For `--llm` inference, check: `OPENAI_API_KEY` / `ANTHROPIC_API_KEY` / `GEMINI_API_KEY` / `GOOGLE_API_KEY`. Absent → still proceed; AST-based extraction and all of W3/W4/W5 work with zero keys.

---

## Editing contract YAML — write rules by file

Sponsio contract YAMLs split into **two trust zones** with different
write rules. Pick the right zone before any edit; the runtime's
self-modify pack enforces the host-zone rules, but cross-zone slips
are still a config-correctness bug we'd rather avoid up-front.

### Zone A — project YAML (you may add additively)

Path: `/sponsio.yaml` — the file `sponsio onboard` writes
into the user's repo. This evolves through every onboard / scan
cycle. **Adding** new contracts via `Edit` (extending
`old_string`) is the supported workflow.

Three legal write modes:

1. **Add a new contract** — `Edit` with `new_string` extending
   `old_string` (the invariant: `old_string ⊆ new_string`):

   ```text
   old_string  = the verbatim tail of the existing file ending at
                 the last contract entry (or the last `contracts:`
                 line if the list is empty)
   new_string  = old_string + "\n      - "
   ```

2. **Tune an existing pack-shipped rule** — never edit the rule
   directly; append a `customized:` entry:

   ```yaml
   customized:
     - match: { desc: "" }
       A: ""   # to relax
       # or args: [...]                                     # to retune thresholds
       # or disabled: true                                  # to silence (last resort)
   ```

3. **Run `sponsio scan`** for bulk additions from code / policy,
   merges additively and writes atomically:

   ```bash
   sponsio scan  -o ./sponsio.yaml --append
   ```

### Zone B — host bucket + plugin bundle YAMLs (user-only — never write directly)

Paths:
- `~/.sponsio/plugins/{{HOST_BUCKET}}/sponsio.yaml`             (this host's runtime library)
- `~/.sponsio/plugins/{{HOST_BUCKET_SUBAGENT}}/sponsio.yaml`    (this host's subagent library)
- `~/.sponsio/plugins//sponsio.yaml`                 (per-plugin / per-MCP-server bundle — github, filesystem, my-plugin, …)

These files govern *your own future tool calls*. The runtime
self-modify pack blocks every Edit / Write / MultiEdit you'd attempt
against them — for the host bucket because rewriting your own rules
is privilege escalation, and for the per-plugin bundles for the same
reason (they constrain the plugin tools you'll call later). The
`{{HOST_BUCKET}}` placeholders above are baked in at skill install
time (`_host_cursor`, `_host_claude_code`, `_host_openclaw`, …) so
each host only loses write access to its own bucket.

**You must NOT** use `Edit`, `Write`, `MultiEdit`, or `Bash` with
shell redirects (`>`, `>>`, `tee`, `sed -i`, `cp`, `mv`, `rm`, `dd`)
on any path under `~/.sponsio/plugins/`. The legitimate update
paths are:

- **CLI** (you can run via `Bash`):
  ```bash
  sponsio plugin install             # copy a fresh bundled starter
  sponsio plugin scan --apply              # regenerate per-plugin bundle
  sponsio plugin show                # surface what's loaded
  ```
- **Hand-edit by the user** in their text editor.

For customizations the user agreed to during a tuning conversation, do
NOT ghostwrite the YAML they should paste. Contract content in
Zone B has exactly four legitimate sources: bundle libraries
(`sponsio plugin install`), CLI extraction (`sponsio plugin scan`,
`sponsio scan`, `sponsio onboard`), the user's own keystrokes, and
`customized:` blocks the user authors themselves. An LLM-composed
snippet has none of those provenances — it's configuration with no
audit trail.

The flow:

1. Restate the user's intent in plain English and identify the
   shipped rule it affects. `sponsio plugin show ` prints the
   `desc:` of every loaded rule; quote a desc verbatim from that
   output if you need to refer to one — do NOT compose YAML around
   it.
2. Tell the user the file path and describe the change in words
   ("add a `customized:` entry beside `contracts:` whose
   `match.desc` matches the rule you want to silence, with
   `disabled: true`"). Point them at the existing pack's syntax for
   reference. Let them write the YAML themselves.
3. When they say they're done, run
   `sponsio validate --config ~/.sponsio/plugins//sponsio.yaml`
   and help debug if it doesn't parse.

### Forbidden write modes (universal)

- **`Write` on any contract YAML above** — overwrites the whole
  file in one go; bypasses the additive evidence even when the
  result happens to be a superset.
- **`Edit` on a Zone-B path** — denied by the self-modify pack
  regardless of additive intent.
- **`Edit` on a Zone-A path where `new_string` does NOT contain
  `old_string`** — a modification or deletion masquerading as an
  edit; treat as forbidden.
- **`MultiEdit` on any contract YAML** — same shape as `Write`.
- **`Bash` with shell write operators** (`>`, `>>`, `tee`,
  `sed -i`, `cp`, `mv`, `rm`, `dd`) targeting any of these paths —
  the runtime blocks Zone B; treat Zone A the same way.

### Why this matters

The user's invariant: *adding* contracts is always allowed; *modifying* or *deleting* existing ones is not.  Following this protocol makes that invariant easy to see at the diff level (`old_string ⊆ new_string`).  When the user audits your edits later, "was anything removed or changed?" reduces to a string-containment check.

### If you genuinely need to remove a rule

You don't.  Use `customized: ... disabled: true` (an additive edit that silences the rule) or ask the user to delete it by hand.  The agent never has authority to remove its own contracts.

### Pattern generality — match operator intent, not demo data

When the operator's NL says "block public gists" or "cap files at 3", write the rule against the operator's **literal intent**.  Do not infer file extensions, content types, naming conventions, or path structures from sample data, demo fixtures, or examples you've seen — unless the operator explicitly named them.

Concrete: a regex like `(\.md"\s*:.*?){4,}` matches only keys ending in `.md`, which means a 4-file gist of `.json` / `.txt` / `.csv` / extension-less keys passes freely.  If the operator said "cap files at 3", the right form is `(\".+?\"\s*:\s*\{){4,}` — any 4+ keys.  Same principle for path globs (`/work/notes/.*\.md` vs `/work/notes/.+`), `arg_field_has` value patterns, and `match:` selectors.

If the operator's intent **IS** demo-specific ("block any `.md` dump from this notes plugin"), keep the narrow pattern but record the assumption in the contract `desc:` so a later reviewer sees the constraint instead of inferring a bug.

#### The flip side — don't broaden past what the operator named

The operator's NL also has a *verb scope*.  When a policy says "no destructive verbs against AWS" the agent must not emit `\baws\s+` (matches every `aws` invocation including `aws s3 ls` / `aws sts get-caller-identity`).  The regex must require **both** the provider **and** a destructive-verb token from the policy.

Concrete:

| Policy phrase | Wrong (overbroad) | Right (verb-anchored) |
|---|---|---|
| "no destructive AWS calls" | `\baws\s+` | `\baws\s+(rds\|s3api\|ec2)\s+(delete-\|terminate-)\w+\b` |
| "no destructive gcloud calls" | `\bgcloud\s+` | `\bgcloud\s+\w+\s+(delete\|destroy\|drain)\b` |
| "no destructive Railway control plane" | `api\.railway\.app` | `(curl\|http\|wget)[^\|;&]*-X\s+DELETE[^\|;&]*\bapi\.railway\.app\b` |
| "no DROP TABLE" | `DROP` | `\bDROP\s+TABLE\b` |

The shipped packs already follow this convention (see `sponsio:incident/cursor-railway-wipe`).  When you extract from a policy doc, mirror the pack style: every command-shape regex is `(host or tool prefix) AND (destructive verb the operator named)`.  Bare provider prefixes are false-positive factories — every routine `aws s3 ls` in a CI script becomes a violation.

If the operator named providers exhaustively in prose ("Railway, Fly, Render, Supabase, Vercel, Cloudflare, Heroku, AWS, GCP"), keep all named providers, each anchored to its own verb set.  Do not collapse them into a single broad alternation that drops the verb anchor.

---

## W1 — Initial setup

Goal: from "project has no Sponsio" to "agent runs under observe
mode with a sane contract file".

The CLI now has a one-shot wizard that covers the common path —
detect framework + IDEs, ask which to install, dispatch
``sponsio onboard`` / ``sponsio host install`` / ``sponsio skill
install`` accordingly, then verify.  W1 is just orchestrating
that wizard, not reimplementing it.

### Steps

1. Run the wizard.

   ```bash
   sponsio init                                                    # interactive TTY
   sponsio init --apply 'framework=;ides=:,...;mode=observe'
                                                                   # non-interactive
   ```

   Picks string format:
     - ``framework=``.  ``none`` is "bare loop, generic
       ``guard.guard_before/after`` wiring"; an empty
       ``framework=`` skips the onboard step entirely.
     - ``ides=:,...`` per-IDE pick.  ```` is
       ``none`` / ``skill`` (drop SKILL.md only) / ``full`` (host
       hooks + SKILL.md, the canonical "protect this IDE" pick).
     - ``mode=observe|enforce``.  Default observe; enforce flips
       are W4's job.

   Use ``sponsio init --plan ''`` first to surface the
   exact commands the wizard will run, especially when you're
   non-interactive.  Surface ``sponsio init``'s output to the user
   verbatim — the panel + preview + recap blocks are designed to
   be readable as-is.

2. Patch the agent entry file (only when ``framework`` ≠ ``""``).

   ```bash
   sponsio onboard . --emit-context > /tmp/sponsio-onboard-context.json
   ```

   Read the JSON.  Pick the entry file in this priority:
     1. ``entry_file_candidates`` has exactly one strong match.
     2. Else dedupe ``tool_inventory[*].filepath`` — one file, use it.
     3. Else stop and ask the user.

   If the file already imports ``from sponsio.`` (Python)
   or ``from "@sponsio/sdk"`` (TS), it's already wrapped — skip.
   Otherwise splice ``wrap_snippet`` from the JSON: imports +
   guard construction at the top, wrap site adapted to the file's
   actual idiom (canonical
   ``create_react_agent(model, guard.wrap(tools))`` if present,
   else adapt — e.g. ``tools_by_name = guard.wrap(TOOLS).tools_by_name``
   for a name-keyed dispatch loop).  Show the diff before writing.

3. Verify.

   ```bash
   sponsio doctor
   sponsio validate --config sponsio.yaml
   ```

   Surface every warning / fail line verbatim.  If ``sponsio doctor``
   FAILED (not warned, failed), stop here — don't let the user run
   their agent thinking the install is healthy when it isn't.

4. Explain observe mode explicitly: "Nothing is blocked on day 1.
   Every contract is still evaluated; violations are logged to
   ``~/.sponsio/sessions//*.jsonl``.  Use ``sponsio report
   --since 24h`` after a day of real traffic to see what would have
   been blocked.  When you're ready to flip, that's W4."

### Beyond W1 — pointers

Onboarding is just install + wire + verify.  These are SEPARATE
workflows, not extensions of W1:

  - **Author tighter contracts** from a policy doc / threat model /
    actually-scanned codebase → **W2** (audit & refine).
  - **Tune host-plugin libraries** (Bash / Read / Write / MCP gating
    in this Claude Code or Cursor session) → invoke the
    ``sponsio-claude-code:configure`` skill (or the cursor analog).
    That skill owns ``sponsio plugin scan`` / ``sponsio plugin
    append`` / per-MCP-server library generation.  W1 doesn't
    duplicate it.
  - **Move from observe to enforce** → **W4**.
  - **Something doesn't fire / fires wrong** → **W5**.

### Choosing the write target — Zone A vs Zone B

``sponsio init``'s axes already encode the destination decision:

  - Axis 1 (framework wrap, picked at non-empty / non-``none``)
    → writes ``/sponsio.yaml``.  This is **Zone A** —
    governs the LLM agent the user is wiring Sponsio INTO.  You may
    Edit/Write this file; ``sponsio validate --config ``
    after.
  - Axis 2 (per-IDE level=full) → writes
    ``~/.sponsio/plugins/_host_/sponsio.yaml`` via
    ``sponsio host install``.  This is **Zone B** — governs the
    HOST agent (i.e. you, Claude Code / Cursor).  Edit/Write/
    MultiEdit are denied by the self-modify pack; the only way to
    extend it from inside the host is ``sponsio plugin append``.

If a user later asks you to add rules and the destination is
ambiguous (project rules vs host-IDE rules), ask:

> "These rules — should they govern (a) the LLM agent your project
> deploys (Zone A: ``/sponsio.yaml``), or (b) my own tool
> calls inside this IDE (Zone B: ``~/.sponsio/plugins/_host_/
> sponsio.yaml``)?"

Two destinations need two files; conflating them silently breaks
one or both.

### Adding rules to Zone B (host bucket) — `sponsio plugin append`

When a Zone-B addition is the right call, you can't Edit/Write the
host yaml directly.  Use the append CLI:

```bash
# 1. Write the new rules to a staging file OUTSIDE Zone B (project
#    root is fine).  Never name it sponsio.yaml — collides with
#    project-config.
sponsio plugin append --from  --target  --dry-run
sponsio plugin append --from  --target 
rm      # delete after success
```

``plugin append`` is structurally additive: it rejects anything
beyond ``contracts:`` entries — no ``customized:``, no
``disabled:``, no desc collisions, no top-level keys.  Tell the
user up front you'll be running this on their behalf so they're
not surprised when it appears.

### Auto-selected packs

`sponsio onboa

…

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [SponsioLabs](https://github.com/SponsioLabs)
- **Source:** [SponsioLabs/Sponsio](https://github.com/SponsioLabs/Sponsio)
- **License:** Apache-2.0
- **Homepage:** https://sponsio.dev/

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** yes
- **Filesystem access:** no
- **Shell / process execution:** yes
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: flagged — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-sponsiolabs-sponsio-sponsio
- Seller: https://agentstack.voostack.com/s/sponsiolabs
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
