Metadata-Version: 2.4
Name: pico-agent
Version: 0.2.0
Summary: A pico agent framework with LangChain integration.
Author-email: David Perez Cabrera <dperezcabrera@gmail.com>
License: MIT License
        
        Copyright (c) 2025 David Pérez Cabrera
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
        
Project-URL: Homepage, https://github.com/dperezcabrera/pico-agent
Project-URL: Repository, https://github.com/dperezcabrera/pico-agent
Project-URL: Issue Tracker, https://github.com/dperezcabrera/pico-agent/issues
Keywords: ioc,di,dependency injection,agent,llm,langchain,langgraph,ai
Classifier: Development Status :: 4 - Beta
Classifier: Framework :: AsyncIO
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: pico-ioc>=2.2.0
Requires-Dist: pydantic>=2.0
Requires-Dist: langchain>=0.2.0
Requires-Dist: langgraph
Requires-Dist: langchain-core
Requires-Dist: langchain-community
Requires-Dist: langchain-model-profiles
Provides-Extra: openai
Requires-Dist: langchain-openai; extra == "openai"
Provides-Extra: google
Requires-Dist: langchain-google-genai; extra == "google"
Provides-Extra: anthropic
Requires-Dist: langchain-anthropic; extra == "anthropic"
Provides-Extra: community
Requires-Dist: langchain-community; extra == "community"
Provides-Extra: all
Requires-Dist: langchain-openai; extra == "all"
Requires-Dist: langchain-google-genai; extra == "all"
Requires-Dist: langchain-anthropic; extra == "all"
Requires-Dist: langchain-community; extra == "all"
Dynamic: license-file

# 📦 pico-agent

[![PyPI](https://img.shields.io/pypi/v/pico-agent.svg)](https://pypi.org/project/pico-agent/)
[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/dperezcabrera/pico-agent)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
![CI (tox matrix)](https://github.com/dperezcabrera/pico-agent/actions/workflows/ci.yml/badge.svg)
[![codecov](https://codecov.io/gh/dperezcabrera/pico-agent/branch/main/graph/badge.svg)](https://codecov.io/gh/dperezcabrera/pico-agent)
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=dperezcabrera_pico-agent&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=dperezcabrera_pico-agent)
[![Duplicated Lines (%)](https://sonarcloud.io/api/project_badges/measure?project=dperezcabrera_pico-agent&metric=duplicated_lines_density)](https://sonarcloud.io/summary/new_code?id=dperezcabrera_pico-agent)
[![Maintainability Rating](https://sonarcloud.io/api/project_badges/measure?project=dperezcabrera_pico-agent&metric=sqale_rating)](https://sonarcloud.io/summary/new_code?id=dperezcabrera_pico-agent)


# Pico-Agent

**[Pico-Agent](https://github.com/dperezcabrera/pico-agent)** is a lightweight, protocol-based framework for building modular AI agents using dependency injection.

It eliminates the boilerplate of manually managing LLM chains, prompts, and tools. Instead, you declare **what** you want the agent to do using Python Protocols, and the framework handles **how** to execute it via **[Pico-IoC](https://github.com/dperezcabrera/pico-ioc)**.

> 🤖 **Protocol-First Design**
> 💉 **True Dependency Injection**
> 🧠 **Smart Model Routing**
> 🔄 **Multi-Agent Orchestration**
> 🔌 **LLM Agnostic (LangChain based)**

-----

## 🎯 Why pico-agent?

Most agent frameworks require you to instantiate classes, manually bind tools, and hardcode model names. Pico-Agent moves this complexity into the IoC container, promoting clean architecture and testability.

| Feature | Standard Approach | Pico-Agent |
|----------|-------------------|------------|
| **Definition** | Concrete Classes / Functions | Python Protocols (Interfaces) |
| **Discovery** | Manual Instantiation | Auto-scanning via IoC |
| **Tools** | Manual Binding | DI Injection & Name Reference |
| **Configuration** | Global Env Vars | Injected Configuration Components |
| **Orchestration** | Complex Chains | Agents using Agents as Tools |

-----

## 🧱 Core Features

  - **Declarative Agents:** Use `@agent` on standard `typing.Protocol`.
  - **Capability Routing:** Request `FAST`, `SMART`, `CODING` capabilities instead of specific model names.
  - **Auto-Discovery:** Leverages `pico-ioc` 2.2+ custom scanners to find agents automatically.
  - **Type-Safe:** Full support for Pydantic input/output schemas.
  - **ReAct Loops:** Built-in support for reasoning loops and tool usage.

-----

## 📦 Installation

```bash
pip install pico-agent
```

Install with specific provider support:

```bash
pip install "pico-agent[openai,google]"
```

-----

## 🚀 Quick Example

### 1\. Define the Agent Protocol

The method signature defines the tool input. The `@agent` decorator configures everything else.

```python
from typing import Protocol
from pico_agent import agent, AgentCapability, AgentType

@agent(
    name="translator",
    capability=AgentCapability.FAST,  # Uses a faster/cheaper model
    system_prompt="You are a professional translator.",
    user_prompt_template="Translate this to Spanish: {text}",
    agent_type=AgentType.ONE_SHOT
)
class TranslatorAgent(Protocol):
    def translate(self, text: str) -> str: ...
```

### 2\. Configure Credentials

Inject the centralized `LLMConfig` and set your keys. This avoids hardcoded environment variable lookups inside the library.

```python
import os
from pico_ioc import component, configure
from pico_agent import LLMConfig

@component
class AppConfig:
    @configure
    def setup_llm(self, config: LLMConfig):
        # Load from Env, Vault, AWS Secrets, etc.
        config.api_keys["openai"] = os.getenv("OPENAI_API_KEY")
        config.api_keys["google"] = os.getenv("GOOGLE_API_KEY")
```

### 3\. Run the Application

pico-agent includes its own `init()` that wraps `pico_ioc.init()` with automatic module inclusion and plugin discovery:

```python
from pico_agent import init
from app.agents import TranslatorAgent

def main():
    # Scans modules, finds agents, wires dependencies
    container = init(modules=["app"])

    # Get your agent instance (auto-generated proxy)
    translator = container.get(TranslatorAgent)

    result = translator.translate(text="Dependency Injection is cool")
    print(result)

if __name__ == "__main__":
    main()
```

You can also use `pico_ioc.init()` directly — just include `"pico_agent"` in your modules list:

```python
from pico_ioc import init

container = init(modules=["pico_agent", "app"])
```

-----

## 🛠 Advanced Usage

### ReAct Agents & Tools

Agents can use any dependency in the container as a tool.

```python
# 1. Define a tool (standard component)
from pico_ioc import component

@component
class Calculator:
    def add(self, a: int, b: int) -> int:
        """Adds two numbers."""
        return a + b

# 2. Define the Agent
@agent(
    name="math_expert",
    capability=AgentCapability.REASONING,
    agent_type=AgentType.REACT,  # Enables Reasoning Loop
    tools=["calculator"],        # Reference tool by name (snake_case of class)
    max_iterations=5
)
class MathAgent(Protocol):
    def solve(self, problem: str) -> str: ...
```

### Multi-Agent Orchestration

An agent can use other agents as tools simply by referencing them.

```python
@agent(
    name="orchestrator",
    capability=AgentCapability.SMART,
    system_prompt="Coordinate the sub-agents to solve the task.",
    # Inject other agents as tools available to this LLM
    agents=["translator", "math_expert"] 
)
class Orchestrator(Protocol):
    def handle_request(self, task: str) -> str: ...
```

-----

## ⚙️ Model Routing & Configuration

`pico-agent` uses semantic capabilities to route to specific models. You can configure this globally using a configurer.

```python
from pico_ioc import component, configure
from pico_agent.router import ModelRouter, AgentCapability

@component
class RouterConfig:
    @configure
    def configure_router(self, router: ModelRouter):
        # Update default mappings
        router.update_mapping(AgentCapability.FAST, "openai:gpt-5-mini")
        router.update_mapping(AgentCapability.SMART, "anthropic:claude-4-5-sonnet")
        
        # You can also use "provider:model" syntax
        router.update_mapping(AgentCapability.CODING, "deepseek:deepseek-coder")
```

-----

## 🔌 With pico-boot

If you use [pico-boot](https://github.com/dperezcabrera/pico-boot), pico-agent is automatically discovered via entry points — no need to include it in your modules list:

```python
from pico_boot import init

container = init(modules=["app"])
# pico-agent is auto-discovered and loaded!
```

-----

## 🧪 Testing

Testing is simple because you can mock the underlying `LLMFactory` or the agent protocol itself.

```python
from unittest.mock import MagicMock
from pico_ioc import init
from pico_agent import LLMFactory, LLM

def test_my_agent():
    mock_llm = MagicMock(spec=LLM)
    mock_llm.invoke.return_value = "Mocked Response"
    
    mock_factory = MagicMock(spec=LLMFactory)
    mock_factory.create.return_value = mock_llm
    mock_factory.return_value = mock_factory # For singleton resolution

    container = init(
        modules=["pico_agent", "my_app"],
        overrides={LLMFactory: mock_factory},
    )
    
    agent = container.get(MyAgent)
    assert agent.run("test") == "Mocked Response"
```

-----

## 🤖 Claude Code Skills

This project includes pre-designed skills for [Claude Code](https://claude.ai/claude-code), enabling AI-assisted development with pico-agent patterns.

| Skill | Command | Description |
|-------|---------|-------------|
| **Pico Agent Creator** | `/pico-agent` | Creates LLM agents with tools, prompts and configuration |
| **Pico Test Generator** | `/pico-tests` | Generates tests for pico-framework components |

See [Skills documentation](docs/skills.md) for full details and installation instructions.

---

## 📝 License

This project is licensed under the MIT License.
