Skip to main content

Soup

Soup is a provider-agnostic Agent Skills router for LLMs.

You define a large number of Agent Skills (rules, best practices, instructions) — in code, as SKILL.md files or with remote sources. On every LLM call, Soup injects only the skills that are actually relevant to the request.

Why?

Monolithic prompts do not scale once your skill catalog spans multiple domains, tools, and workflows. Soup routes only the relevant Agent Skills for each request, so you do not ship unrelated instruction blocks on every call.

  • Reducing tokens sent on each call.
  • Improving context quality (only relevant instructions).
  • Avoiding monolithic prompts.
  • Making context modular, composable and reusable across projects, using the open Agent Skills format so your skills are portable.

Soup is completely independent from the LLM provider. It works with OpenAI, Anthropic, Gemini, Ollama, LiteLLM, LangChain, etc. — because it just transforms the prompt/messages you already have.

Install

pip install soup-ai        # or: uv add soup-ai

Requires Python 3.12+. Runtime dependencies are pydantic and pyyaml.

Even faster: let your coding agent do it

This repo ships its own Agent Skill, skills/integrate-soup, that automates the whole setup. Copy the skills/integrate-soup directory into your project (e.g. Cursor users can drop it into .cursor/skills/), then ask your agent something like "use the integrate-soup skill to add Soup to this project." It scans your codebase for where LLM prompts/messages are built, drafts a concrete integration plan, and — once you approve it — splits your existing prompts into skills and wires soup.prepare() into your call sites for you.

Quickstart

from soup import Soup

soup = Soup()

soup.register(
    name="react-ui",
    description="React UI implementation patterns. Use for React components, hooks, and layout tasks.",
    instructions="""
Use React 19 function components.
Prefer composition and colocated state.
Keep accessibility semantics in markup.
""",
    tags=["react", "ui", "components"],
)

soup.register(
    name="sql-postgres",
    description="Postgres SQL guidance. Use for query design and indexing tasks.",
    instructions="""
Use parameterized queries.
Add indexes for frequent filters.
Review query plans before optimization.
""",
    tags=["sql", "postgres", "database"],
)

# String prompt in, string prompt out:
prompt = soup.prepare("I need guidance on building a React dashboard card component with hooks.")

# ...or chat messages in, chat messages out:
messages = soup.prepare(
    [{"role": "user", "content": "I need guidance on building a React dashboard card component with hooks."}]
)

The integration is meant to be invisible:

response = client.responses.create(
    model="gpt-5",
    input=soup.prepare(messages),
)

Registering skills

register() is the single entry point. It dispatches on what you give it.

# 1. Define a skill in code (name, description and instructions are required):
soup.register(
    name="pdf-processing",
    description="Extract PDF text, fill forms, and merge files. Use for PDF tasks.",
    instructions="Use pypdf for extraction...",
)

# 2. Load a single local skill directory (a folder containing SKILL.md):
soup.register("./skills/pdf-processing")

# 3. Load a whole local collection (a folder of skill directories):
soup.register("./skills")

# 4. Load from a GitHub or GitLab repo over raw HTTP (no git required):
soup.register("https://github.com/vercel-labs/skills", ref="main")
soup.register("https://gitlab.com/group/project", ref="main")

Soup's optional routing behavior stays simple. For a single skill, pass overrides as keyword arguments; for a collection or repo, pass per-skill options:

soup.register("./skills/pdf-processing", dependencies=["files"], version="1.0")

soup.register(
    "./skills",
    options={
        "pdf-processing": {"dependencies": ["files"], "priority": 10},
        "data-analysis": {"version": "2.1"},
    },
)

Core concepts

Skill

A Skill is the atomic unit of context and follows the Agent Skills spec.

Field Group Type Purpose
name required str Unique identifier (spec naming rules; matches dir name).
description required str What it does and when to use it; primary routing signal.
instructions required str The context injected; the SKILL.md Markdown body.
license spec str | None License name or bundled file reference.
compatibility spec str | None Environment requirements (max 500 chars).
allowed_tools spec list[str] Pre-approved tools (allowed-tools, experimental).
metadata spec dict[str, str] Arbitrary key-value mapping; stores Soup extensions.
tags soup list[str] Keywords for tag-aware selection.
examples soup list[str] "Training phrases" also used for BM25 selection, rendered after the instructions.
priority soup int Tie-breaker; reserved for future compression.
dependencies soup list[str] Skills to always include alongside this one.
extends soup list[str] Parent skills this one specializes (composition).
version soup str | None Version string for sharing/reuse.

SKILL.md files

A SKILL.md file is YAML frontmatter followed by a Markdown body. Soup's own routing extensions live under spec-compliant metadata (string values are canonical; comma-separated strings are parsed into lists):

---
name: pdf-processing
description: Extract PDF text, fill forms, and merge files. Use for PDF tasks.
license: MIT
metadata:
  version: "1.0"
  dependencies: "files"
  tags: "pdf, forms, documents"
  priority: "10"
---

Use pypdf for extraction. Validate inputs before merging...

The Markdown body becomes the skill's instructions. The name must follow the spec rules (lowercase letters, numbers and hyphens, 1–64 chars) and match its directory name.

Composition & versioning (extends)

Skills are composable and versionable, so you can build hierarchies and reuse rules across projects without duplication:

soup.register(name="frontend", description="Frontend basics. Use for UI work.",
              tags=["ui"], instructions="Accessibility first.")
soup.register(name="react", description="React rules. Use for React apps.",
              version="1.0", extends=["frontend"], tags=["react"], instructions="Use hooks.")
soup.register(name="nextjs", description="Next.js conventions. Use for Next.js.",
              version="2.1", extends=["react"], tags=["nextjs"], instructions="Use the app router.")

Selecting nextjs automatically pulls in react and frontend, rendered parent-first. dependencies work the same way (transitive inclusion) but express a companion relationship rather than specialization. Cycles are detected and broken, and missing references raise MissingDependencyError (configurable).

Selection strategies

By default, Soup uses a single built-in selector: BM25Strategy (no embeddings, no vector DB, no RAG).

If you need custom behavior, you can still add your own strategy:

from soup import SelectionStrategy

class RegexStrategy(SelectionStrategy):
    def select(self, query, skills):
        ...

soup.add_strategy(RegexStrategy())

For architecture and design details, see docs/architecture.md.

Examples

See examples/ for complete, runnable integrations with OpenAI, OpenRouter, Anthropic, LiteLLM and Ollama.

Development

uv venv && uv pip install -e ".[dev]"
ruff check .
mypy
basedpyright
pytest --cov=soup --cov-report=term-missing

Roadmap

V1 loads SKILL.md instructions and metadata only. Full Agent Skills support — exposing bundled scripts/, references/, and assets/ files to the LLM/runtime — is tracked as a follow-up.

Changelog

See CHANGELOG.md for release notes.

License

MIT.

Metadata

Release files for soup-ai 0.2.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for soup-ai 0.2.1
File Size Uploaded Provenance
soup_ai-0.2.1.tar.gz 46.0 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for soup-ai 0.2.1
File Interpreter ABI Platform
soup_ai-0.2.1-py3-none-any.whl Python 3 none any Details

Total release size: 77.4 kB

Release files / soup_ai-0.2.1.tar.gz

Download URL soup_ai-0.2.1.tar.gz
Size 46.0 kB
Tags Source
SHA-256 checksum
How to use checksums
9edb592749664d007db3aa6293401080d53d25035445ad4e9ec5e208fbd12216
BLAKE2b-256 checksum
How to use checksums
e3848d7fe493629164317517acede2714864ab71c40f05e27353516897d565d3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 7, 2026.

Transparency log

Release files / soup_ai-0.2.1-py3-none-any.whl

Download URL soup_ai-0.2.1-py3-none-any.whl
Size 31.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d368669e583729ee7533feac04516fe13c6d9ba78c1123b6ecfb7e5580beeec8
BLAKE2b-256 checksum
How to use checksums
de3fab677f4bcab0f2b863428b4c712c8cf38e2250ddda1651623e607f372df7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 7, 2026.

Transparency log

Security for soup-ai 0.2.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for soup_ai-0.2.1.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 7, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.2.1 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page