Cantus
A polyphonic framework for composing LLM agent harnesses — designed for teaching on Google Colab.
Cantus (Latin: song, chant) is a teaching-oriented LLM agent framework. Two protocol kinds (Skill / Memory) plus hook helpers (Analyzer / Validator) and the cantus.workflows building blocks let learners and operators compose agents on Google Colab, backed by 4-bit-quantised Gemma 4 models.
The Chinese-speaking LLM community refers to prompt engineering as yǒng chàng — literally "to chant" or "to incant". Cantus treats agent composition as a polyphonic chant — each protocol is a voice, and together they form an agent that sings back.
In Cantus, your code IS the chant — every Skill, Memory, and Agent is a verse that wields the LLM. The PyPI name cantus-agent makes the relationship explicit: you chant, the agent answers.
Open in Colab — 5-minute path
The fastest way to experience Cantus is to launch the bundled notebooks directly:
See notebooks/README.md for the recommended order and tag-pinning conventions.
Install
# PyPI (recommended — reproducible, no Git clone). Distribution name is `cantus-agent`; import name remains `cantus`.
pip install cantus-agent==0.6.0
# Git source — escape hatch for tracking main, a feature branch, or a specific commit
pip install git+https://github.com/schola-cantorum/cantus@v0.6.0
pip install git+https://github.com/schola-cantorum/cantus@main
pip install git+https://github.com/schola-cantorum/cantus@<commit-sha>
The runtime extras (Gemma 4 + transformers + bitsandbytes) require:
pip install 'cantus-agent[runtime]==0.6.0'
The serve extras (v0.4.0 — FastAPI app factory; pulls fastapi, uvicorn, pydantic-settings):
pip install 'cantus-agent[serve]==0.6.0'
Serve Quickstart (v0.4.0)
Spin up the bundled FastAPI app on 127.0.0.1:8765 with a fresh Registry:
from cantus.serve import serve
from cantus.core.registry import Registry
import uvicorn
app = serve(Registry())
uvicorn.run(app, host="127.0.0.1", port=8765)
Hit the health endpoint to confirm the server is up:
curl http://localhost:8765/health
# {"status":"ok","cantus_version":"0.6.0"}
Desktop (Win / macOS / Linux)
Desktop and laptop users — see docs/quickstart-desktop.md for a 5-minute API-key-backed walkthrough that works on Windows, macOS, and Linux. The Colab path below remains the recommended route for 4-bit local Gemma.
30-second Quickstart
from cantus import skill, Agent, mount_drive_and_load
@skill
def add(a: int, b: int) -> int:
"""Add two integers."""
return a + b
model_handle = mount_drive_and_load(variant="E4B")
agent = Agent(model=model_handle)
result = agent.run("What is 17 plus 25?")
final = result.stream[-1] # FinalAnswerAction when the loop converged
print(getattr(final, "answer", final))
Multi-provider quickstart (v0.2.1)
Tier 2 ChatModel adapters let you point the same Agent at OpenAI, Anthropic, Google Gemini, Groq, or NVIDIA NIM instead of local Gemma. You MUST wrap a ChatModel with ChatModelAsHandle before passing it to Agent — the Agent only speaks the Tier 1 .generate(prompt) -> str protocol.
OpenAI (install pip install 'cantus-agent[openai]', set OPENAI_API_KEY):
from cantus import Agent, ChatModelAsHandle, load_chat_model
chat = load_chat_model("openai/gpt-4o-mini")
agent = Agent(model=ChatModelAsHandle(chat, system="You are terse."))
result = agent.run("What is 17 plus 25?")
final = result.stream[-1] # FinalAnswerAction when the loop converged
print(getattr(final, "answer", final))
Anthropic (install pip install 'cantus-agent[anthropic]', set ANTHROPIC_API_KEY):
from cantus import Agent, ChatModelAsHandle, load_chat_model
chat = load_chat_model("anthropic/claude-sonnet-4-6")
agent = Agent(model=ChatModelAsHandle(chat, system="You are terse."))
result = agent.run("What is 17 plus 25?")
final = result.stream[-1] # FinalAnswerAction when the loop converged
print(getattr(final, "answer", final))
Google Gemini (install pip install 'cantus-agent[google]', set GOOGLE_API_KEY; uses google-genai, not the legacy google-generativeai):
from cantus import Agent, ChatModelAsHandle, load_chat_model
chat = load_chat_model("google/gemini-2.0-flash")
agent = Agent(model=ChatModelAsHandle(chat, system="You are terse."))
result = agent.run("What is 17 plus 25?")
final = result.stream[-1] # FinalAnswerAction when the loop converged
print(getattr(final, "answer", final))
Groq (install pip install 'cantus-agent[groq]', set GROQ_API_KEY):
from cantus import Agent, ChatModelAsHandle, load_chat_model
chat = load_chat_model("groq/llama-3.3-70b-versatile")
agent = Agent(model=ChatModelAsHandle(chat, system="You are terse."))
result = agent.run("What is 17 plus 25?")
final = result.stream[-1] # FinalAnswerAction when the loop converged
print(getattr(final, "answer", final))
NVIDIA NIM (install pip install 'cantus-agent[openai]' — NIM runs on the OpenAI SDK, so there is no cantus-agent[nvidia] extras; set NVIDIA_API_KEY):
from cantus import Agent, ChatModelAsHandle, load_chat_model
chat = load_chat_model("nvidia/meta/llama-3.3-70b-instruct")
agent = Agent(model=ChatModelAsHandle(chat, system="You are terse."))
result = agent.run("What is 17 plus 25?")
final = result.stream[-1] # FinalAnswerAction when the loop converged
print(getattr(final, "answer", final))
cantus-agent[providers] installs the four primary adapters (OpenAI / Anthropic / Google / Groq) at once. NVIDIA NIM ships through cantus-agent[openai] since the NIM endpoint is OpenAI-compatible. cantus intentionally does not depend on LiteLLM at any layer, and the Google extras pulls only google-genai (the new unified Gemini API SDK), never google-generativeai.
Two protocol kinds + hook helpers + workflows building blocks
Two protocol kinds (the things cantus formally registers and dispatches):
- Skill — a function the agent can call (tool use). Decorate with
@skillor subclassSkill. - Memory — conversation state and retrieval memory; ships
ShortTermMemory,BM25Memory,EmbeddingMemory,MarkdownMemory, plus theAutoMemorywrapper that exposes any backend to the LLM as four Skills.
Hook helpers (pre- / post-loop tooling, not protocol kinds):
- Analyzer — turn user input into a structured result before entering the agent loop. Use
@analyzeror subclassAnalyzer. - Validator — post-process the agent's output, returning a
Resultthat decides pass or retry. Use@validatoror subclassValidator.
Workflows building block:
cantus.workflows— composition templates that chain skills, analyzers, and validators into a fixed flow. No longer a protocol kind in v0.3.0; pick the building block that fits your scenario.
Documentation
The docs are published as a VitePress site in English and 繁體中文, with the source under docs/site/. Run npm run docs:build to build it locally. The docs.yml workflow builds both locales on every push and pull request; publishing to Cloudflare Pages is configured outside this repository, so no deploy step lives here. Two other artifacts round it out: a NotebookLM-ready corpus under docs/api/, and an interactive manual at cantus-manual.html.
The site is the canonical home for the overview, quickstart, protocol guides, and cookbook. Two references live outside it:
- llms.txt — single-file priming document for external LLMs
- Developer LLM Wiki — internal contributor knowledge base (research, coding style, architecture, future work)
Upgrade Guides
Per-version migration guides for breaking changes between adjacent releases:
- v0.2 → v0.3
- v0.3 → v0.3.1
- v0.3 → v0.3.2
- v0.3 → v0.3.3
- v0.3.3 → v0.3.4
- v0.3.4 → v0.3.5
- v0.3.5 → v0.3.6
- v0.3.6 → v0.4.0
- v0.4.0 → v0.4.1
- v0.4.1 → v0.4.2
- v0.4.2 → v0.4.3
- v0.4.3 → v0.4.4
- v0.4.4 → v0.4.5
- v0.4.5 → v0.4.6
- v0.4.6 → v0.4.7
- v0.4.7 → v0.5.0
- v0.5.0 → v0.6.0
The CHANGELOG.md lists everything else (additive features, internal changes, security notes).
License
ECL-2.0 — Educational Community License, Version 2.0. See LICENSE.
Metadata
Release files for cantus-agent 0.6.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| cantus_agent-0.6.0.tar.gz | 213.1 kB | With provenance | Details for cantus_agent-0.6.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| cantus_agent-0.6.0-py3-none-any.whl | Python 3 | none | any | Details for cantus_agent-0.6.0-py3-none-any.whl |
Total release size: 368.7 kB
Release files / cantus_agent-0.6.0.tar.gz
| Download URL | cantus_agent-0.6.0.tar.gz |
|---|---|
| Size | 213.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
bd5e702b743bd48861a1f610f93e873070a743ca6081dffdf6c972f0716b6faa
|
|
BLAKE2b-256 checksum How to use checksums |
642370e599a62280fc36043c71ff61411c7663c9df428d94ba39951f850af1be
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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 Sep 5, 2026.
Transparency logRelease files / cantus_agent-0.6.0-py3-none-any.whl
| Download URL | cantus_agent-0.6.0-py3-none-any.whl |
|---|---|
| Size | 155.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e7c8a9c38fb7c20e085134e10bdc8af2cd97663d2c75bd2f0685975255359a5d
|
|
BLAKE2b-256 checksum How to use checksums |
4eda700ebd2c2f00d70f1200e0c432f77abf4e6149c77221ff6cf7327bfd2b7f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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 Sep 5, 2026.
Transparency logSecurity for cantus-agent 0.6.0
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.
Attestation for cantus_agent-0.6.0.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 Sep 5, 2026.
Transparency logA 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.