Teotl
An autonomous agent framework for Python: planner-worker execution, built-in guardrails, and any LLM provider.
Teotl splits agent work between a planner (a strong model that runs once to write a step-by-step plan) and a worker (a cheaper, faster model that executes each step). Every tool call passes through a policy-based guardrail layer before it runs, and a harness keeps plans, progress, costs, and audit logs on disk so long-running missions can pause, resume, and be inspected.
Status: alpha (v0.2.0). APIs may change between minor versions.
Features
- Planner-worker harness: plan once with a capable model, execute many steps with a cheap one
- Guardrails:
minimal/standard/strictpolicies, bash command analysis, prompt-injection checks, rate and cost limits, progressive trust - Multi-provider: Anthropic Claude, OpenAI, Google Gemini, Ollama (local), or LiteLLM
- Your own tools and skills: register Python functions as tools (with per-tool risk levels) and add
SKILL.mdskills with scripts; skills load on demand to keep prompts small - Memory: optional local vector memory with automatic context compaction
- Harness artifacts:
PLAN.md,PROGRESS.md, state checkpoints, cost tracking, append-only audit log - Credentials: OS keyring, encrypted file, or AWS Secrets Manager storage
- CLI and dashboard: interactive chat, onboarding wizard, and a web dashboard for monitoring agents
Installation
pip install "teotl[anthropic]"
Pick the extras you need:
| Extra | Adds |
|---|---|
anthropic |
Claude models |
openai |
OpenAI models |
google |
Gemini models |
ollama |
Local models via Ollama |
litellm |
Any provider via LiteLLM |
memory |
Vector memory (sentence-transformers, sqlite-vec) |
security |
OS keyring and encrypted credential storage |
web |
Web dashboard |
aws |
AWS Secrets Manager credential backend |
all |
Everything above |
Requires Python 3.11 or newer.
Quick start
Set an API key:
export ANTHROPIC_API_KEY="sk-ant-..."
A single agent
import asyncio
from teotl import Agent
from teotl.core.provider import AnthropicProvider
async def main():
agent = Agent(
provider=AnthropicProvider(model="claude-sonnet-5-5"),
instructions="You are a careful code reviewer.",
skills=["filesystem", "git"],
policy="standard", # or "strict" / "minimal"
)
response = await agent.run("Summarize the last 5 commits in this repo.")
print(response.text)
print(f"Cost: ${response.cost:.4f}")
asyncio.run(main())
Planner-worker
import asyncio
from pathlib import Path
from teotl.core.provider import AnthropicProvider
from teotl.primitives.harness import PlannerWorkerHarness
async def main():
harness = PlannerWorkerHarness(
agent_id="code-quality",
planner_provider=AnthropicProvider(model="claude-sonnet-5-5"), # plans once
worker_provider=AnthropicProvider(model="claude-haiku-4-5"), # executes each step
workspace_dir=Path(".teotl/code-quality"),
worker_skills=["filesystem", "git"],
)
plan = await harness.plan(goals="Add type hints and docstrings to public functions in src/.")
print(f"Plan has {plan.total_steps} steps (see PLAN.md)")
while not harness.is_complete():
result = await harness.execute_next_step()
print(f"Step {result.step.number}: {'ok' if result.success else result.error}")
asyncio.run(main())
The harness writes PLAN.md and PROGRESS.md into the workspace, so you can read, edit, or resume a plan at any point. By default it asks for approval before starting each new execution cycle.
Other providers
from teotl.core.provider import GeminiProvider, OllamaProvider, OpenAIProvider
GeminiProvider(model="gemini-2.5-flash") # GOOGLE_API_KEY
OpenAIProvider(model="gpt-4.1") # OPENAI_API_KEY
OllamaProvider(model="llama3.1") # local, no key
You can mix providers, for example a Claude planner with a local Ollama worker.
Command line
teotl --help
teotl onboard # interactive setup wizard: provider, skills, policy, planner-worker config
teotl chat # interactive chat with an agent
teotl security # manage credentials and security settings
Guardrails
Every tool call is classified and checked against a policy before it executes. This happens outside the model's context, so a prompt can't talk its way past it.
strict: read-only by default; writes and shell commands need approvalstandard: common development actions allowed; destructive or sensitive actions need approvalminimal: for trusted sandboxes
Built-in protections include bash command analysis (for example blocking rm -rf / and piping remote scripts to a shell), prompt-injection checks on instructions and incoming messages, per-agent rate and cost limits, and a trust score that grows with repeated safe behavior. See docs/GUARDRAILS.md.
Your own skills and tools
Teotl is built to be extended. Add tools (Python functions the model can call) and skills (instructions, plus optional scripts, that teach the model how to do a task). They work with every provider: Claude, OpenAI, Gemini, and Ollama (with a model that supports tool calling).
Tools
def lookup_order(order_id: str) -> str:
return f"Order {order_id}: shipped" # call your database or API here
agent.register_tool(
name="lookup_order",
description="Look up an order's status by ID",
handler=lookup_order, # a regular or async function
parameters={
"type": "object",
"properties": {"order_id": {"type": "string"}},
"required": ["order_id"],
},
risk="low", # "medium" or "high" asks for confirmation under the standard policy
)
Declare risk="medium" or higher for anything that changes data or contacts people, so guardrails ask before it runs.
Skills
A skill is a folder with a SKILL.md file (YAML frontmatter plus instructions), and optionally scripts or reference files:
~/.teotl/skills/invoice-report/
├── SKILL.md
└── scripts/report.py
---
name: invoice-report
description: Summarize unpaid invoices
triggers: [unpaid invoices]
---
Run `python scripts/report.py` from the skill directory, then summarize the output.
agent = Agent(provider=provider, skills=["invoice-report", "filesystem"])
Only each skill's one-line description is in the prompt until it's needed. The skill's full instructions (with its directory path) are loaded when your message names it or matches a trigger, or when the model calls the built-in load_skill tool.
Teotl looks for skills in:
- the skills bundled with the package (
filesystem,git,github,web,claude_code,spec_kit) ~/.teotl/skills/(move the data directory withTEOTL_HOME)- any directories listed in
TEOTL_SKILLS_PATH(colon-separated)
See docs/CUSTOM_SKILLS_QUICKSTART.md and docs/SKILLS_GUIDE.md.
Examples
| Example | What it shows |
|---|---|
examples/planner_worker_demo.py |
Planner-worker plan and execute loop |
examples/devops_agent/ |
Agent that triages GitHub issues and proposes fixes |
examples/supervisor_demo.py |
Supervised execution with approvals |
examples/custom_skill_example.py |
Writing your own skill |
examples/full_config_reference.yaml |
Every YAML configuration option |
examples/social_media_agent.yaml |
Content-drafting agent that writes social posts to files |
Documentation
Roadmap
- Planner-worker harness
- Guardrails, credential storage, audit log, cost tracking
- Anthropic, OpenAI, Gemini, Ollama, LiteLLM providers
- YAML configuration for multi-agent setups
- Published benchmark results (GAIA and cost comparisons)
- More end-to-end examples (code review, test generation)
- Deeper MCP integration
Contributing
Bug reports, ideas, and pull requests are welcome.
- Questions and ideas: Discussions
- Bugs and feature requests: Issues
- Code: see CONTRIBUTING.md
git clone https://github.com/keithdit4e/teotl
cd teotl
pip install -e ".[dev,anthropic]"
pytest
Report security issues privately. See SECURITY.md.
License
MIT © Keith Foster
Metadata
Release files for teotl 0.2.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| teotl-0.2.3.tar.gz | 343.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| teotl-0.2.3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 670.0 kB
Release files / teotl-0.2.3.tar.gz
| Download URL | teotl-0.2.3.tar.gz |
|---|---|
| Size | 343.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c1ee3b33d9d3d7be0e3b0916fd630eac52285fa880c9594994571c1333cd0914
|
|
BLAKE2b-256 checksum How to use checksums |
099f8805ce9423663111e715c8923378fda073ccd8e3b6ad29c4deb8c1d3e192
|
| 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 30, 2026.
Transparency logRelease files / teotl-0.2.3-py3-none-any.whl
| Download URL | teotl-0.2.3-py3-none-any.whl |
|---|---|
| Size | 326.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b88161e856a34ecf9ab7fc3c6334ba4dcfa8378d2ec51be10919669fb4c4a080
|
|
BLAKE2b-256 checksum How to use checksums |
ee6725d773e77c2c59a0d1521d928f9d15e279d613643650a3ba72fac3548aef
|
| 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 30, 2026.
Transparency log