A multi-agent orchestration framework for Python develpoed by Sajib Hossain
Project description
Squadria
squadria is a lightweight Python framework for orchestrating role-based AI agents.
It gives you simple building blocks to define an assistant persona, assign tasks, and
run multi-step workflows where one step can feed context into the next.
Features
- Persona-driven agents (
Actor) with configurableLLMabstraction - Structured task objects (
Job) with expected output guidance - Sequential, parallel, and hierarchical orchestration (
Squad) - Plugin abstraction (
Plugin) with automatic parameter schema generation - Small, readable core focused on extensibility
Installation
pip install squadria
Quick Start
Set your provider API key first (example for OpenAI):
export OPENAI_API_KEY="your_api_key_here"
Sequential Execution
Create and run a simple two-step workflow where each job can use prior job context:
from squadria import Actor, Job, Squad
researcher = Actor(
title="Senior Tech Researcher",
objective="Find practical trends in AI tooling.",
expertise="You analyze current AI engineering practices.",
tone=["concise", "analytical"],
language="English",
model="gpt-4o-mini",
verbose=True,
trace_level="minimal",
guardrails=["personal_info", "medicine"],
)
writer = Actor(
title="Technical Writer",
objective="Turn research into a clear summary.",
expertise="You explain technical topics for developers.",
tone=["clear", "engaging"],
language="English",
model="gpt-4o-mini",
verbose=True,
)
research_job = Job(
description="List 3 current trends in AI agent frameworks.",
expected_output="Three bullet points with one sentence each.",
actor=researcher,
max_retries=10,
)
writing_job = Job(
description="Write a short 2-paragraph overview from the research context.",
expected_output="Two short paragraphs.",
actor=writer,
)
squad = Squad(
actors=[researcher, writer],
jobs=[research_job, writing_job],
process="sequential",
trace_level="minimal",
)
final_result = squad.kickoff()
print(final_result)
Using a Dedicated LLM Object
Use LLM(...) when you want model-level controls in one place.
from squadria import Actor, Job, LLM, Squad
llm = LLM(
model="gpt-4o-mini",
temperature=0.2,
timeout=120,
max_tokens=1200,
)
agent = Actor(
title="Concise Analyst",
objective="Answer clearly and briefly.",
expertise="You provide practical summaries.",
tone=["concise"],
llm=llm,
verbose=True,
)
job = Job(
description="Summarize why orchestration frameworks are useful.",
expected_output="A short practical summary.",
actor=agent,
)
squad = Squad(actors=[agent], jobs=[job], process="sequential")
print(squad.kickoff())
Supported LLM(...) parameters include:
modeltemperaturetimeoutmax_tokenstop_pfrequency_penaltypresence_penaltystopbase_urlapi_keycustom_params(forwarded to LiteLLM)
custom_params cannot override reserved keys: model, messages, tools.
Define Client Once, Reuse Across LLMs
With a client-first setup, you can define one client and reuse it for multiple LLM objects.
from squadria import Actor, Job, LLM, LiteLLMClient, Squad
shared_client = LiteLLMClient()
research_llm = LLM(model="gpt-4o-mini", temperature=0.2, client=shared_client)
writer_llm = LLM(model="gpt-4o-mini", temperature=0.7, client=shared_client)
researcher = Actor(
title="Researcher",
objective="Find key points.",
expertise="You summarize concise findings.",
llm=research_llm,
)
writer = Actor(
title="Writer",
objective="Write clean final output.",
expertise="You convert notes to readable prose.",
llm=writer_llm,
)
jobs = [
Job(
description="List three practical insights about orchestration frameworks.",
expected_output="Three concise bullets.",
actor=researcher,
),
Job(
description="Turn the insights into two short paragraphs.",
expected_output="Two clear paragraphs.",
actor=writer,
),
]
squad = Squad(actors=[researcher, writer], jobs=jobs, process="sequential")
print(squad.kickoff())
Custom Client Implementation
If you want full transport control, implement BaseLLMClient and plug it into LLM.
from typing import Any, Dict
from squadria import BaseLLMClient, LLM
class MyClient(BaseLLMClient):
def complete(self, payload: Dict[str, Any]) -> Any:
# Send payload to your own gateway/provider here.
# Return a provider response object (any shape).
return {"text": "Final Output: Hello from custom client"}
def extract_text(self, response: Any) -> str:
# Convert your provider response shape into plain text.
return str(response.get("text", ""))
llm = LLM(
model="my-gateway-model",
client=MyClient(),
)
Custom LLM Implementation
Use BaseLLM when you want a fully custom provider/client implementation.
from typing import Dict, List, Optional
from squadria import Actor, BaseLLM, Job, Squad
class CustomLLM(BaseLLM):
def call(self, messages, tools: Optional[List[dict]] = None) -> str:
if isinstance(messages, str):
prompt = messages
else:
prompt = "\n".join(
f"{item.get('role', 'user')}: {item.get('content', '')}" for item in messages
)
return f"Final Output: Custom provider response for -> {prompt[:120]}"
custom_llm = CustomLLM(model="my-custom-model")
agent = Actor(
title="Custom LLM Agent",
objective="Use a custom model backend.",
expertise="You route through a custom LLM implementation.",
tone=["concise"],
llm=custom_llm,
)
job = Job(
description="Explain why custom LLM interfaces are useful.",
expected_output="A short practical explanation.",
actor=agent,
)
squad = Squad(actors=[agent], jobs=[job], process="sequential")
print(squad.kickoff())
Parallel Execution
Use parallel mode when jobs are independent and do not need chained context.
from squadria import Actor, Job, Squad
researcher = Actor(
title="Research Analyst",
objective="Collect concise findings.",
expertise="You summarize important points quickly.",
tone=["concise", "analytical"],
language="English",
model="gpt-4o-mini",
verbose=True,
)
reviewer = Actor(
title="Risk Reviewer",
objective="Identify practical risks clearly.",
expertise="You review technical trade-offs.",
tone=["direct", "clear"],
language="English",
model="gpt-4o-mini",
verbose=True,
)
benefits_job = Job(
description="List 3 practical benefits of multi-agent orchestration.",
expected_output="Three bullet points.",
actor=researcher,
max_retries=10,
)
risks_job = Job(
description="List 3 practical risks of multi-agent orchestration.",
expected_output="Three bullet points.",
actor=reviewer,
max_retries=10,
)
squad = Squad(
actors=[researcher, reviewer],
jobs=[benefits_job, risks_job],
process="parallel",
trace_level="minimal",
)
final_result = squad.kickoff()
print(final_result)
Hierarchical Execution
Use a manager actor to plan subtasks, delegate them to workers, and synthesize final output.
from squadria import Actor, Job, Squad
manager = Actor(
title="Engineering Manager",
objective="Break goals into tasks and synthesize final output.",
expertise="You are strong at decomposition and delegation.",
tone=["structured", "decisive"],
language="English",
model="gpt-4o-mini",
)
researcher = Actor(
title="Research Analyst",
objective="Collect evidence quickly.",
expertise="You summarize findings with references.",
tone=["concise"],
language="English",
model="gpt-4o-mini",
)
writer = Actor(
title="Technical Writer",
objective="Write clear final prose.",
expertise="You communicate complex ideas simply.",
tone=["clear"],
language="English",
model="gpt-4o-mini",
)
top_level_job = Job(
description="Create a short brief on modern AI agent orchestration patterns.",
expected_output="A concise, structured brief.",
actor=manager,
max_retries=10,
)
squad = Squad(
actors=[manager, researcher, writer],
jobs=[top_level_job],
process="hierarchical",
manager=manager,
)
result = squad.kickoff()
print(result)
Core Concepts
Persona Configuration
Defines the personality and constraints for an agent:
title: role nameobjective: what the agent tries to achieveexpertise: domain background for groundingtone: list of style adjectiveslanguage: response language (default:English)
Actor accepts these fields directly as constructor parameters.
Actor
Wraps LLM execution. It:
- auto-generates a unique
id(UUID string) - accepts persona fields directly:
title,objective,expertise, optionaltone, optionallanguage - accepts either
model="..."orllm=LLM(...) - accepts optional
guardrails(built-in and custom) - when
verbose=True, prints step-by-step console traces - accepts optional
trace_level(minimalordetailed, default:minimal) - builds a system prompt from persona data
- optionally includes plugin descriptions
- delegates model calls through the
LLMobject - returns the model output text
LLM, BaseLLM, and Client Layer
LLMis Squadria's default model wrapper and supports common generation parameters.BaseLLMis the abstract interface for custom providers.BaseLLMClientis the transport contract used byLLMand defines:complete(payload)to send requestsextract_text(response)to normalize response text
LiteLLMClientis the default production client implementation.- You can pass
llm=LLM(...)to anActorfor advanced configuration, or usemodel="..."for quick setup.
Guardrails
Guardrails are optional Actor-level safety constraints.
Built-in guardrail keys:
personal_infomedicineself_harmviolenceillegal_activitiesfinancial_advice
You can configure them with:
- built-ins as strings:
guardrails=["medicine", "personal_info"] - object-style custom rules:
guardrails=["medicine", {"name": "no_legal_advice", "rule": "Do not provide legal advice.", "severity": "high"}]
For custom rules, only rule is required. name and severity are optional metadata.
Job
Represents a single task with:
descriptionexpected_outputactor- optional
context - optional
max_retries(default:10) - auto-generated
id(UUID string)
Squad
Supports three process modes:
sequential: chains context from one job to the nextparallel: executes all jobs concurrently and returns combined ordered outputhierarchical: manager plans worker tasks (JSON plan), workers execute, manager synthesizes final output- auto-generated
id(UUID string) - optional
trace_level(minimalordetailed, default:minimal)
Plugin
Wraps a Python function into a reusable capability object and generates a JSON schema for function arguments using Pydantic.
Plugin Example
from squadria.plugins.base import Plugin
def add(a: int, b: int) -> int:
return a + b
math_plugin = Plugin(
name="adder",
description="Adds two numbers",
func=add,
)
print(math_plugin.execute(a=2, b=3)) # 5
print(math_plugin.get_description()) # includes auto-generated schema
API Surface
Top-level imports available from squadria:
ActorBaseLLMBaseLLMClientJobLLMLiteLLMClientPluginSquad
Persona schema classes are internal implementation details and are not part of the top-level public interface.
Notes
- Current orchestration modes are
sequential,parallel, andhierarchical. - Hierarchical mode requires
manager=...and at least one worker actor. - Ensure your API key is set for the model provider you choose.
- This framework is intentionally minimal and designed to be extended.
Project details
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 squadria-0.1.9.tar.gz.
File metadata
- Download URL: squadria-0.1.9.tar.gz
- Upload date:
- Size: 13.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
611b42cb4130a4281d361499958fcea2d8d6d17c1f18cc9bc0c83137106644a5
|
|
| MD5 |
e7465994518b74770355c72d0aa58d2e
|
|
| BLAKE2b-256 |
2ea13b672461e417ea95842310f6db1ee4d450df3a51d832a0685962067dc072
|
File details
Details for the file squadria-0.1.9-py3-none-any.whl.
File metadata
- Download URL: squadria-0.1.9-py3-none-any.whl
- Upload date:
- Size: 20.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dd4b2b8d2f63b12ff64ff6502cd0983fccfd76362fa5b208fc757d5aecfc6b87
|
|
| MD5 |
ae38e18eb0efac9bb515ac89f14837db
|
|
| BLAKE2b-256 |
01f8cdf4630db69f442fffe1017b7fc1835320105b13e1d7b9d33b2be8c14588
|