# 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-skills`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **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/ts/packages/sdk/skills
- **Website:** https://sponsio.dev/

## Install

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

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** |
| 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** |
| 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.

---

## W1 — Initial setup

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

### Steps

1. Run the one-shot entry point:

   ```bash
   sponsio onboard . --apply
   ```

   `onboard` detects framework (langgraph / langchain / crewai / openai_agents / claude_agent / vercel-ai / no-framework), picks an LLM provider if available, auto-selects contract packs (see "Auto-selected packs" below), writes `sponsio.yaml` in **observe** mode, and with `--apply` patches the agent entry file with a two-line wrap (backup at `.sponsio.bak`). Falls back to printing the patch snippet if the framework isn't auto-patchable.

2. After `onboard` finishes, show the user three things — do not skip any:
   - The generated `sponsio.yaml` (read it back and summarize: packs included, tools renamed, mode).
   - The applied patch (from `report.apply_result.diff`) or the printed snippet.
   - Any `sponsio doctor` warn/fail lines.

3. Explain observe mode explicitly: "Nothing is blocked on day 1. Every contract is still evaluated; violations are logged to `~/.sponsio/sessions//*.jsonl` and (if a dashboard is configured) pushed there. Use `sponsio report --since 24h` after a day of real traffic to see what would have been blocked."

4. If `sponsio doctor` failed (not warned, failed), stop and surface it — don't let the user run their agent thinking the install is healthy when it isn't.

### Auto-selected packs

`sponsio onboard` uses simple, conservative heuristics:

| Pack | Auto-included when… | Notes |
|---|---|---|
| `sponsio:core/universal` | Always | Empty stub, kept so existing `include:` lines don't error. |
| `sponsio:core/runaway` | Framework runs a multi-step loop (langgraph/crewai/…) | token budget, delegation depth, loop detection; no LLM calls |
| `sponsio:capability/shell` | A tool name matches `{bash, shell, exec, execute, execute_command, run_command, run_shell, run_bash, terminal, subprocess}` | Auto-fills `tool_rename:` if the user's tool name isn't the canonical `exec` |
| `sponsio:capability/filesystem` | A tool name matches `{read, read_file, open_file, write, write_file, edit, edit_file, apply_patch, patch_file, ...}` | Auto-fills `tool_rename:` and `workspace:` |
| `sponsio:incident/openclaw` | Never auto-included — opt-in only | CVE-derived rules for a specific vendor incident |

`sponsio packs` lists all shipped packs with live rule counts and include specs.

### Do NOT

- Do NOT edit `sponsio/contracts/*.yaml` inside the installed package — those are the shipped packs; they're read-only. Adjustments go in the user's `sponsio.yaml` via `overrides:` or `contracts:`.
- Do NOT flip `mode: enforce` during W1. The whole point of observe mode is to find false positives before they break production.

---

## W2 — Audit & refine (from scratch, or deepen an existing yaml)

Goal: produce or improve a `sponsio.yaml` from code / policy docs / traces, and explain every contract in plain language.

### Decide which sources to use

Sponsio contracts come from four sources, mixable in one yaml:

| # | Source | What it is | Command |
|---|---|---|---|
| 1 | **Shipped packs** | Pre-built, parameterized rule sets (`sponsio:core/universal`, `sponsio:capability/shell`, …) | Hand-add `include: [sponsio:]` — or W1's `onboard` does it automatically |
| 2 | **Extraction** | AST + optional LLM inference from your code / policy docs / execution traces | `sponsio scan  [--llm] [--policy ] [-t ]` |
| 3 | **User input** | An NL sentence or a structured dict the user writes | Hand-edit `sponsio.yaml`; validate a single NL string with `sponsio validate ""` |
| 4 | **Pattern library** | Deterministic parameterized templates (`rate_limit`, `must_precede`, `arg_blacklist`, …) — full list via `sponsio patterns` | `sponsio patterns` to browse; hand-write the YAML entry |

Match the user's input to the source(s):

- "Explain / review my `sponsio.yaml`" → source 1 and/or others already applied; jump to "Explain contracts" below.
- "Scan my agent code" → source 2, code-only.
- "We have a security policy document" → source 2, add `--policy  --llm`.
- "I know the pattern I want but not the syntax" → source 4, then show them the yaml entry.

If ambiguous: ask ONE question — "(a) scan your code, or (b) extract from a policy document?"

### Run scan (when extraction is needed)

```bash
# AST-only (fast, no keys):
sponsio scan  --agent  -o ./sponsio.yaml

# + LLM inference:
sponsio scan  --agent  --llm -o ./sponsio.yaml

# + policy doc:
sponsio scan  --policy  --llm -o ./sponsio.yaml
```

Scan auto-validates before writing; only contracts that parse cleanly are saved. Source-tagged with `source: scan` / `source: policy`.

### Validate existing yaml (explain-only path)

```bash
sponsio validate --config ./sponsio.yaml --json
```

JSON shape per entry: `{nl, ok, type: "det"|"unknown", pattern, formula, agent, section}`. `ok: false` means the NL didn't match any pattern — surface those as "ambiguous — needs refinement".

### Explain contracts (use this as the report template)

```markdown
## Sponsio contract summary — 

**Setup**:  contracts total, . Mode: .

### Active packs
- `sponsio:core/universal` (empty stub, kept so existing `include:` lines don't error)
- `sponsio:capability/shell` (11 det) — guards on 

### Contracts explained
Each contract is an assumption → enforcement pair. State the assumption explicitly even when absent ("unconditional"), because the assumption defines **when** the enforcement applies.

- **When**: the agent has called `modify_order`
  **Then**: `get_order_details` must have happened earlier.
  **Runtime effect**: if unmet, the call is blocked (or logged, in observe) and the agent is told why.

- **When**: unconditional
  **Then**: `send_email` is called at most 5 times per session.
  **Runtime effect**: the 6th call is blocked.

### Ambiguous contracts (optional — only if validate flagged any)
- `"..."` — didn't match any pattern; rephrase or rewrite as a structured dict.

### Next steps
1. Review; prune anything that doesn't fit the agent's real job.
2. Run in observe mode for 1–2 days.
3. `sponsio report --since 24h` to see what would have been blocked (W3).
4. Prune false positives, then flip `mode: enforce` (W4).
```

Keep it dense. Don't pad with "consult an expert" disclaimers — the user is already using the expert.

---

## W3 — Tune in observe

Goal: look at what Sponsio logged during observe mode, decide which violations are real vs false positives, and adjust `sponsio.yaml` accordingly. **Never flip mode during this workflow.**

### Steps

1. Pull the violation report:

   ```bash
   sponsio report --agent  --since 24h
   ```

2. For each violation cluster:
   - **Real violation** → leave the contract as-is. Note it for the user.
   - **False positive** → adjust `sponsio.yaml`. Use this decision tree:

     | Situation | Edit |
     |---|---|
     | Pack-shipped rule is too strict globally | Add an `overrides: - match: {desc: "..."}` entry with tuned args |
     | Pack-shipped rule doesn't apply to this agent at all | `overrides: - match: {...}, disabled: true` |
     | Rule's threshold is wrong (e.g. rate_limit N) | `overrides: ..., args: [, ]` |
     | Rule conflicts with a legitimate workflow that Sponsio couldn't infer | Weaken via an `A:` (assumption) so it only fires in the specific unsafe context |
     | User's own hand-written contract is wrong | Edit `contracts:` directly |

   Use `desc`, `pattern`, `pack_source`, or `source` as the `match:` key (see the YAML schema below).

3. Do NOT edit a contract you haven't seen a violation for. "It looks strict" isn't a reason to remove it in observe mode — it's the reason to leave it.

4. After each edit, verify the yaml still parses: `sponsio validate --config sponsio.yaml`.

### Using assumptions to relax (the right way)

When a rule is correct in principle but too broad in practice, prefer adding an `A:` over disabling:

```yaml
overrides:
  - match: { desc: "Each exec call needs its own confirm_reconfirmed" }
    A: "called `confirm_reconfirmed`"
```

With the assumption, the rule stays silent until the integration actually emits the marker — it's vacuous-true without the precondition, enforced once the precondition holds. This is the preferred pattern for "I want this rule eventually but not today".

---

## W4 — Flip to enforce

Goal: move from observe to enforce with regression confidence — no more logging, actual blocking. **This is a production change**; don't skip the checks.

### Steps

1. **Regression test on real traces.** Pick a representative trace from `~/.sponsio/sessions//` and replay:

   ```bash
   sponsio check --trace  --config sponsio.yaml --agent 
   ```

   Exit 0 = every contract passes on this trace. Non-zero = something would have been blocked. If non-zero, go back to W3.

2. **Flip the mode.** Two options:

   a. Pin in yaml (permanent):
      ```yaml
      runtime:
        mode: enforce
      ```

   b. Flip via env var (reversible, no code change):
      ```bash
      SPONSIO_MODE=enforce python -m your_agent
      ```

   Precedence: explicit ctor arg > env > yaml > default.

3. **Keep the dashboard.** In production, point OTEL export at Sponsio's collector (`POST /api/otel/v1/traces`) or keep using `~/.sponsio/sessions/*.jsonl` + `sponsio report`. Don't run `sponsio serve --dev` in prod — that's a dev tool.

4. Tell the user how to roll back: `SPONSIO_MODE=observe` without redeploying.

---

## W5 — Troubleshoot

Common symptoms and their fixes.

### "LLM extraction call failed: cannot import name 'genai' from 'google'"

User has `google-generativeai` not `google-genai`. Fix:
```bash
pip install -U 'sponsio[llm]'
```

### "ConfigError: include 'sponsio:...': pack must define exactly one agent named '*' (the template)"

The pack file's `agents:` uses a literal agent name instead of `"*"`. If it's a user pack, rename. If it's a shipped pack, that's a Sponsio bug — file an issue.

### "ConfigError: Agent '': pattern '' uses the '/' placeholder but the agent has no 'workspace:' set."

Add `workspace: /path/to/project/root` under the agent in `sponsio.yaml`. The `filesystem` and `openclaw` packs need this.

### "A rule I expected to fire isn't firing."

Check in this order:

1. `sponsio validate --config sponsio.yaml --json` — does the contract parse? `ok: false` means it was silently dropped.
2. The tool name in the contract matches the actual tool name the agent calls (LangGraph `node_id` vs the `@tool` Python name is a common trap; see `tool_rename:`).
3. The rule has an `A:` (assumption) that isn't holding. Look at the trace — is the precondition ever true?

### "A rule is firing that shouldn't."

Jump to W3. Don't disable in a panic — add a targeted `overrides:` entry with a `match:` clause, so the adjustment is traceable.

### "`sponsio onboard` detected the wrong framework."

`onboard` doesn't currently take a `--framework` override flag. Fall back to the manual two-step:

```bash
sponsio init --agent 
sponsio scan  --agent  -o sponsio.yaml
```

Then hand-apply the integration snippet for your framework from the "Integration snippets" section below.

---

## YAML schema (what contracts look like)

Every contract is an `(assumption, enforcement)` pair. Both short keys (`A` / `E`) and long keys (`assumption` / `enforcement`) are accepted; mixing both forms of the same field in one entry raises `ConfigError`.

```yaml
version: "1"

agents:
  :                        # dict keyed by agent_id, NOT a list
    workspace: /path/to/project      # required by packs that use /

    include:                         # pre-built packs (see W1 "Auto-selected packs")
      - sponsio:core/universal
      - sponsio:capability/shell

    tool_rename:                     # map the pack's canonical names to the
      exec: run_bash                 # host's actual tool names
      read: read_file

    overrides:                       # tune shipped packs without forking them
      - match: { desc: "Each exec call needs its own confirm_reconfirmed" }
        A: "called `confirm_reconfirmed`"
      - match: { pattern: rate_limit, args: [send_email, 5] }
        args: [send_email, 20]
      - match: { pack_source: sponsio:incident/openclaw, desc: "..." }
        disabled: true

    contracts:                       # hand-written + scan-inferred contracts
      # NL form (short keys)
      - A: "called `modify_order`"
        G: "must call `get_order_details` before `modify_order`"
      # Omit A for unconditional
      - G: "tool `send_email` is rate-limited to 5 per session"
      # Structured dict (what scan emits for det patterns)
      - G:
          pattern: must_precede
          args: [check_policy, issue_refund]
          source: scan

runtime:
  mode: observe                      # "observe" | "enforce"
  dashboard: http://localhost:8000   # URL | true | false | null
```

Both `A` and `G` accept: scalar NL string, list (AND), or structured dict `{pattern, args, source?}`.

Placeholders rewritten at include-time: `/` (from agent's `workspace:`), `` (from agent id).

---

## Pattern reference

Full list: `sponsio patterns` (deterministic templates only).

### Core Temporal (14 det)
| Pattern | Meaning |
|---|---|
| `must_precede(A, B)` | A must be called before B |
| `always_followed_by(A, B)` | Every A must eventually be followed by B |
| `no_reversal(A, B)` | Once A fires, B is permanently forbidden |
| `requires_permission(tool, perm)` | Agent must hold `perm` before `tool` |
| `no_data_leak(source, sink)` | Data from source must not reach sink |
| `mutual_exclusion(A, B)` | At most one of A, B per trace |
| `rate_limit(tool, N)` | Tool at most N calls per session |
| `idempotent(tool)` | Tool at most once |
| `deadline(trigger, action, N)` | Action within N steps of trigger |
| `must_confirm(action)` | A confirmation tool must precede action |
| `cooldown(action, N)` | Min N steps between consecutive calls |
| `segregation_of_duty(A, B)` | Same agent can't perform both |
| `bounded_retry

…

## 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:** no
- **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: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-sponsiolabs-sponsio-skills
- 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%.
