Getting started
Praval has two entry paths. Start with direct Agent calls when one agent is
enough. Add Reef and Spores when independent specialists need to collaborate.
Install
python -m pip install praval
Praval supports Python 3.9 through 3.13. Optional capabilities are installed separately:
python -m pip install "praval[memory]"
python -m pip install "praval[storage]"
python -m pip install "praval[mcp]" # Python 3.10+
For a hosted provider, set the corresponding environment variable before running an example:
export OPENAI_API_KEY="..."
# or ANTHROPIC_API_KEY, COHERE_API_KEY, or GEMINI_API_KEY
Passing provider and model explicitly makes an example reproducible. If
they are omitted, Praval resolves its configured defaults and available
credentials.
First path: call a model through Agent
from praval import Agent
assistant = Agent(
"assistant",
provider="openai",
model="gpt-5.4-mini",
system_message="Be concise.",
)
try:
response = assistant.generate("Explain what a Praval Spore carries.")
print(response.content)
print(response.provider, response.model, response.usage)
finally:
assistant.close()
Agent.generate() returns ModelResponse. Its content, provider, model,
usage, tool calls, and raw provider data are available without changing the
application contract for each provider.
The compatibility method returns only a string:
text = assistant.chat("Explain Reef in one sentence.")
Prefer generate() for new code. Use agenerate(), stream(), and
astream() for asynchronous work and normalized streaming events.
Structured output
import json
response = assistant.generate(
"Return one fact about Reef as JSON.",
response_schema={
"type": "object",
"properties": {"fact": {"type": "string"}},
"required": ["fact"],
},
)
fact = json.loads(response.content)["fact"]
The runtime checks that the selected provider profile supports structured output and then sends the schema as a provider constraint. It does not run a second local JSON Schema validation pass.
Second path: collaborate through Reef
A Spore contains routing fields and a structured knowledge dictionary. The
conventional knowledge["type"] value lets decorated agents decide which
messages to handle.
from praval import agent, broadcast, get_reef, start_agents
@agent("researcher", provider="ollama", responds_to=["research_request"])
def researcher(spore):
topic = spore.knowledge["topic"]
broadcast(
{
"type": "research_complete",
"topic": topic,
"finding": f"Evidence collected for {topic}",
}
)
@agent("editor", provider="ollama", responds_to=["research_complete"])
def editor(spore):
print(spore.knowledge["finding"])
start_agents(
researcher,
editor,
initial_data={"type": "research_request", "topic": "agent systems"},
)
reef = get_reef()
reef.wait_for_completion(timeout=30)
reef.shutdown()
This example uses the Ollama preset only to construct credential-free message
handlers; it does not call the local model server. A decorated handler may call
chat() or achat() when it actually needs model output.
wait_for_completion() waits for submitted Reef work. Always shut down Reef
and other resources explicitly in scripts and tests.
When to use each layer
Need |
Start with |
|---|---|
One conversational or tool-using agent |
|
Provider-neutral metadata and usage |
|
Streaming deltas and final events |
|
Multiple reactive specialists |
|
Deterministic application cleanup |
|
External MCP tools |
|
PravalApp owns agents and a Reef for cleanup. In this release it does not
isolate provider registries or redirect agent Reef helpers; see
Application lifecycle.
Local models
Praval connects to an already-running OpenAI-compatible server:
from praval import Agent
local = Agent("local", provider="ollama", model="llama3")
try:
print(local.chat("Say hello."))
finally:
local.close()
The presets are ollama, vllm, lmstudio, and llama-cpp. Text and
streaming are enabled by default. Tools, structured output, reasoning, and
multimodal input require explicit capability configuration for the server you
are using.
Learn by inspecting execution
The Jupyter course explains Agent, Reef, Spore, tools, memory, HITL, MCP, and
voice flows with visible runtime state. Start with
examples/notebooks/course/00_architecture.ipynb.
For a credential-free runtime check:
python examples/model_runtime_fake_provider.py
Next, read Core concepts and API layers, Model Runtime, and the generated API Reference.