A small, composable Python framework for building goal-directed LLM agents (GAME loop + Capability hooks).
Project description
zurvan
A small, composable Python framework for building goal-directed LLM agents.
What it is
zurvan runs a GAME loop — Goals, Actions, Memory, Environment — over
an LLM. Behaviour like plan-first, time-aware, prompt-injection-resistant,
or progress-tracking is composed by passing a list of Capability
instances rather than by subclassing Agent. With no capabilities it
reduces to a plain Goals → Actions → Memory cycle.
LLM providers are abstracted behind AgentLanguage. Built-in subclasses
(via LiteLLM) cover OpenAI, Gemini,
and Groq.
Install
pip install zurvan
Requires Python 3.11+.
Quick start
from zurvan import (
Action,
ActionRegistry,
Agent,
AgentFunctionCallingActionLanguageOpenAI,
Environment,
Goal,
)
def terminate(message: str) -> str:
return message
actions = ActionRegistry()
actions.register(Action(
name="terminate",
function=terminate,
description="End the conversation with a final message.",
parameters={
"type": "object",
"properties": {"message": {"type": "string"}},
"required": ["message"],
},
terminal=True,
))
agent = Agent(
goals=[Goal(priority=1, name="Greet", description="Greet the user warmly.")],
agent_language=AgentFunctionCallingActionLanguageOpenAI(model="openai/gpt-4o-mini"),
action_registry=actions,
environment=Environment(),
)
memory = agent.run("Say hi.")
Pydantic-validated tool inputs
Action accepts either a JSON-Schema dict (parameters=) or a Pydantic
model (input_model=). With a model, the schema sent to the LLM is
derived from the model and the model's args are validated before the
function runs — a ValidationError is caught by Environment and
fed back to the LLM as a failed-tool result, so the model gets a chance
to retry with corrected args.
from typing import Literal
from pydantic import BaseModel
from zurvan import Action
class GetWeatherArgs(BaseModel):
city: str
unit: Literal["c", "f"] = "c"
def get_weather(city: str, unit: str = "c") -> str:
return f"It's nice in {city} ({unit}°)"
action = Action(
name="get_weather",
function=get_weather,
description="Look up the weather for a city.",
input_model=GetWeatherArgs,
)
parameters= and input_model= are mutually exclusive — pass exactly one.
Capabilities
Capabilities hook into every loop phase (init, start_agent_loop,
process_prompt, process_response, process_action, process_result,
process_new_memories, end_agent_loop, should_terminate,
terminate). Compose them — don't subclass Agent.
from zurvan import Agent, CanaryCapability, TimeAwareCapability
agent = Agent(
...,
capabilities=[CanaryCapability(), TimeAwareCapability()],
)
License
MIT.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file zurvan-0.1.0.tar.gz.
File metadata
- Download URL: zurvan-0.1.0.tar.gz
- Upload date:
- Size: 25.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d3146afbc79900889c98162f02bea19fa96ffa6f94c4a4b6a5cfcadde6d57f7f
|
|
| MD5 |
a766d7cd99908da5d80b8ce9b92d2b43
|
|
| BLAKE2b-256 |
ddb6e1029f40daaa74869a55c05523fb2a49ef30abb9d032039157781034e571
|
Provenance
The following attestation bundles were made for zurvan-0.1.0.tar.gz:
Publisher:
release.yml on aliafsahnoudeh/zurvan
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
zurvan-0.1.0.tar.gz -
Subject digest:
d3146afbc79900889c98162f02bea19fa96ffa6f94c4a4b6a5cfcadde6d57f7f - Sigstore transparency entry: 1476977397
- Sigstore integration time:
-
Permalink:
aliafsahnoudeh/zurvan@613a6b0d41ee6127882271932b2883f1c115faec -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/aliafsahnoudeh
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@613a6b0d41ee6127882271932b2883f1c115faec -
Trigger Event:
push
-
Statement type:
File details
Details for the file zurvan-0.1.0-py3-none-any.whl.
File metadata
- Download URL: zurvan-0.1.0-py3-none-any.whl
- Upload date:
- Size: 35.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6a5a9217b926bc21945cdca0fe85e5867900cbf4d2df402fe94ceb3bc0ff80a2
|
|
| MD5 |
eff3371afc4878d4f6d0fd19abc034de
|
|
| BLAKE2b-256 |
1402d33ee833b0061f76e0a4901e3eccaf27a4d97edf9f5000d991f5ea19cadf
|
Provenance
The following attestation bundles were made for zurvan-0.1.0-py3-none-any.whl:
Publisher:
release.yml on aliafsahnoudeh/zurvan
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
zurvan-0.1.0-py3-none-any.whl -
Subject digest:
6a5a9217b926bc21945cdca0fe85e5867900cbf4d2df402fe94ceb3bc0ff80a2 - Sigstore transparency entry: 1476977834
- Sigstore integration time:
-
Permalink:
aliafsahnoudeh/zurvan@613a6b0d41ee6127882271932b2883f1c115faec -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/aliafsahnoudeh
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@613a6b0d41ee6127882271932b2883f1c115faec -
Trigger Event:
push
-
Statement type: