Metadata-Version: 2.4
Name: squadria
Version: 0.1.7
Summary: A multi-agent orchestration framework for Python develpoed by Sajib Hossain
Author: Sajib Hossain
Requires-Python: >=3.10
Requires-Dist: jinja2>=3.0.0
Requires-Dist: litellm>=1.0.0
Requires-Dist: pydantic>=2.0.0
Description-Content-Type: text/markdown

# 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 configurable `LLM` abstraction
- 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

```bash
pip install squadria
```

## Quick Start

Set your provider API key first (example for OpenAI):

```bash
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:

```python
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.

```python
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:

- `model`
- `temperature`
- `timeout`
- `max_tokens`
- `top_p`
- `frequency_penalty`
- `presence_penalty`
- `stop`
- `base_url`
- `api_key`
- `custom_params` (forwarded to LiteLLM)

## Custom LLM Implementation

Use `BaseLLM` when you want a fully custom provider/client implementation.

```python
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.

```python
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.

```python
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 name
- `objective`: what the agent tries to achieve
- `expertise`: domain background for grounding
- `tone`: list of style adjectives
- `language`: 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`, optional `tone`, optional `language`
- accepts either `model="..."` or `llm=LLM(...)`
- accepts optional `guardrails` (built-in and custom)
- when `verbose=True`, prints step-by-step console traces
- accepts optional `trace_level` (`minimal` or `detailed`, default: `minimal`)
- builds a system prompt from persona data
- optionally includes plugin descriptions
- delegates model calls through the `LLM` object
- returns the model output text

### `LLM` and `BaseLLM`

- `LLM` is Squadria's default model wrapper and supports common generation parameters.
- `BaseLLM` is the abstract interface for custom providers.
- You can pass `llm=LLM(...)` to an `Actor` for advanced configuration, or use `model="..."` for quick setup.

### Guardrails

Guardrails are optional Actor-level safety constraints.

Built-in guardrail keys:

- `personal_info`
- `medicine`
- `self_harm`
- `violence`
- `illegal_activities`
- `financial_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:

- `description`
- `expected_output`
- `actor`
- 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 next
- `parallel`: executes all jobs concurrently and returns combined ordered output
- `hierarchical`: manager plans worker tasks (JSON plan), workers execute, manager synthesizes final output
- auto-generated `id` (UUID string)
- optional `trace_level` (`minimal` or `detailed`, default: `minimal`)

### `Plugin`

Wraps a Python function into a reusable capability object and generates a JSON schema
for function arguments using Pydantic.

## Plugin Example

```python
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`:

- `Actor`
- `BaseLLM`
- `Job`
- `LLM`
- `Plugin`
- `Squad`

Persona schema classes are internal implementation details and are not part of the
top-level public interface.

## Notes

- Current orchestration modes are `sequential`, `parallel`, and `hierarchical`.
- 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.
