Metadata-Version: 2.4
Name: async-media-agents
Version: 0.1.0
Summary: A multi-agent workflow for processing audio, image, and video data.
Author-email: Abka012 <fergusonabka012@gmail.com>
License: MIT
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: aiofile==3.11.1
Requires-Dist: annotated-types==0.7.0
Requires-Dist: anyio==4.13.0
Requires-Dist: attrs==26.1.0
Requires-Dist: Authlib==1.7.2
Requires-Dist: beartype==0.22.9
Requires-Dist: cachetools==7.1.3
Requires-Dist: caio==0.9.25
Requires-Dist: certifi==2026.5.20
Requires-Dist: cffi==2.0.0
Requires-Dist: charset-normalizer==3.4.7
Requires-Dist: click==8.4.0
Requires-Dist: cryptography==48.0.0
Requires-Dist: cyclopts==4.15.0
Requires-Dist: dnspython==2.8.0
Requires-Dist: docstring_parser==0.18.0
Requires-Dist: email-validator==2.3.0
Requires-Dist: exceptiongroup==1.3.1
Requires-Dist: fastmcp==3.3.1
Requires-Dist: fastmcp-slim==3.3.1
Requires-Dist: griffelib==2.0.2
Requires-Dist: h11==0.16.0
Requires-Dist: httpcore==1.0.9
Requires-Dist: httpx==0.28.1
Requires-Dist: httpx-sse==0.4.3
Requires-Dist: idna==3.15
Requires-Dist: jaraco.classes==3.4.0
Requires-Dist: jaraco.context==6.1.2
Requires-Dist: jaraco.functools==4.5.0
Requires-Dist: jeepney==0.9.0
Requires-Dist: joserfc==1.6.5
Requires-Dist: jsonpatch==1.33
Requires-Dist: jsonpointer==3.1.1
Requires-Dist: jsonref==1.1.0
Requires-Dist: jsonschema==4.26.0
Requires-Dist: jsonschema-path==0.5.0
Requires-Dist: jsonschema-specifications==2025.9.1
Requires-Dist: keyring==25.7.0
Requires-Dist: langchain==1.3.1
Requires-Dist: langchain-core==1.4.0
Requires-Dist: langchain-protocol==0.0.15
Requires-Dist: langgraph==1.2.1
Requires-Dist: langgraph-checkpoint==4.1.0
Requires-Dist: langgraph-prebuilt==1.1.0
Requires-Dist: langgraph-sdk==0.3.14
Requires-Dist: langsmith==0.8.5
Requires-Dist: markdown-it-py==4.2.0
Requires-Dist: mcp==1.27.1
Requires-Dist: mdurl==0.1.2
Requires-Dist: more-itertools==11.0.2
Requires-Dist: nodejs-wheel-binaries==24.15.0
Requires-Dist: numpy==2.4.6
Requires-Dist: openapi-pydantic==0.5.1
Requires-Dist: opencv-python-headless==4.13.0.92
Requires-Dist: opentelemetry-api==1.42.1
Requires-Dist: orjson==3.11.9
Requires-Dist: ormsgpack==1.12.2
Requires-Dist: packaging==26.2
Requires-Dist: pathable==0.6.0
Requires-Dist: pillow==12.2.0
Requires-Dist: platformdirs==4.9.6
Requires-Dist: py-key-value-aio==0.4.4
Requires-Dist: pycparser==3.0
Requires-Dist: pydantic==2.13.4
Requires-Dist: pydantic-settings==2.14.1
Requires-Dist: pydantic_core==2.46.4
Requires-Dist: Pygments==2.20.0
Requires-Dist: PyJWT==2.13.0
Requires-Dist: pyperclip==1.11.0
Requires-Dist: python-dotenv==1.2.2
Requires-Dist: python-multipart==0.0.29
Requires-Dist: PyYAML==6.0.3
Requires-Dist: referencing==0.37.0
Requires-Dist: requests==2.34.2
Requires-Dist: requests-toolbelt==1.0.0
Requires-Dist: rich==15.0.0
Requires-Dist: rich-rst==2.0.1
Requires-Dist: rpds-py==0.30.0
Requires-Dist: SecretStorage==3.5.0
Requires-Dist: sse-starlette==3.4.4
Requires-Dist: starlette==1.0.1
Requires-Dist: tenacity==9.1.4
Requires-Dist: typing-inspection==0.4.2
Requires-Dist: typing_extensions==4.15.0
Requires-Dist: uncalled-for==0.3.2
Requires-Dist: urllib3==2.7.0
Requires-Dist: uuid_utils==0.16.0
Requires-Dist: uvicorn==0.47.0
Requires-Dist: watchfiles==1.2.0
Requires-Dist: websockets==16.0
Requires-Dist: xxhash==3.7.0
Requires-Dist: zstandard==0.25.0
Provides-Extra: dev
Requires-Dist: pytest; extra == "dev"
Requires-Dist: pytest-asyncio; extra == "dev"
Requires-Dist: flake8; extra == "dev"
Requires-Dist: basedpyright==1.39.5; extra == "dev"
Dynamic: license-file

# async-media-agents

Async Multi-Agent POC using LangGraph + FastMCP + real media processing.

## Overview

A lightweight async multi-agent system that processes images, audio, and video via base64-encoded payloads. Uses LangGraph for workflow orchestration, FastMCP for tool registration, and real processing libraries (Pillow, OpenCV, stdlib `wave`).

## Architecture

```
                User Request
                      |
              SupervisorAgent
                      |
       Fan-out (parallel conditional edge)
      ┌──────────┼──────────┐
      |          |          |
  ImageAgent  AudioAgent VideoAgent
      |          |          |
  Pillow     stdlib wave  OpenCV
  processor   processor   processor
      |          |          |
      └──────────┼──────────┘
           Fan-in to Aggregator
```

## Features

- ✅ **Real media processing** — Powered by Pillow (Images), OpenCV (Video), and stdlib `wave` (Audio).
- ✅ **Parallel execution** — High-performance fan-out/fan-in orchestration using LangGraph.
- ✅ **MCP Integration** — Model Context Protocol support via FastMCP for tool registration.
- ✅ **Robust error handling** — Graceful recovery from corrupt base64 or invalid formats.
- ✅ **Shared state** — Concurrent-safe state management via `Annotated` reducers.
- ✅ **Type Safety** — Comprehensive static analysis with `basedpyright`.

## Requirements

```text
langgraph
langchain
fastmcp
Pillow
opencv-python-headless
numpy
pytest
pytest-asyncio
```

## Setup

### 1. Create and activate a virtual environment

```bash
# Create the virtual environment
python -m venv .venv

# Activate it
source .venv/bin/activate        # Linux / macOS
.venv\Scripts\activate           # Windows (cmd)
```

### 2. Install dependencies

```bash
pip install -r requirements.txt
```

## Project Structure

```text
project/
├── async_media_agents/
│   ├── agents/
│   │   ├── image_agent.py         # Specialized image logic
│   │   ├── audio_agent.py         # Specialized audio logic
│   │   ├── video_agent.py         # Specialized video logic
│   │   └── supervisor.py          # Orchestration & routing
│   │
│   ├── tools/
│   │   ├── mcp_server.py          # FastMCP server registration
│   │   ├── mcp_client.py          # Async client interface
│   │   └── processors/            # Pure processing logic (decoupled)
│   │       ├── image_processor.py # Pillow-based
│   │       ├── audio_processor.py # stdlib wave
│   │       └── video_processor.py # OpenCV-based
│   │
│   ├── graph/
│   │   └── workflow.py            # LangGraph workflow definition
│   │
│   ├── state/
│   │   ├── state.py               # Shared AgentState with reducers
│   │   └── shared_memory.py       # Global shared context utilities
│   │
│   └── __init__.py
│
├── scripts/
│   └── test_workflow.py           # Integration & payload tests
│
├── main.py                         # CLI demo & examples
├── requirements.txt
├── pyproject.toml                  # Project & Tool configuration
└── README.md
```

## Usage

### Run the demo

```bash
python main.py
```

The demo demonstrates three core patterns:
1. **Text-based routing** — Auto-detects task type from user natural language.
2. **Parallel processing** — Simultaneously processes multiple media types via fan-out.
3. **Supervisor workflow** — Uses the Supervisor agent to route to a single target.

### Run tests

Tests can be executed directly or through `pytest`:

```bash
# Direct execution (includes payload generation logs)
python scripts/test_workflow.py

# Using pytest
pytest scripts/test_workflow.py
```

The test suite covers:
- Base64 payload integrity (PNG, WAV, MP4)
- Real metadata extraction via processors
- Parallel transport through the workflow
- Partial payload handling
- Robust error handling for corrupted data

### Programmatic use

```python
from async_media_agents.graph.workflow import Workflow

wf = Workflow()

# Text-based — auto-routes to image/audio/video agent
result = await wf.run("Analyze this image")

# Parallel — feeds base64 to all three agents
result = await wf.run_parallel(
    image_data="base64_encoded_png",
    audio_data="base64_encoded_wav",
    video_data="base64_encoded_mp4",
)
```

## Processing Pipeline

| Media   | Library               | Extracted Metadata                                    |
|---------|-----------------------|-------------------------------------------------------|
| Image   | Pillow                | width, height, format, mode, thumbnail                |
| Audio   | stdlib `wave`         | duration, sample rate, channels, sample width, frames |
| Video   | opencv-python-headless | duration, fps, resolution, frame count, dimensions    |

All processors return structured dicts: `{"status": "success", "metadata": {...}}` or `{"status": "error", "error": "..."}`.

## Static Analysis

The project uses `basedpyright` for type checking:

```bash
pip install basedpyright
basedpyright .
```

Configuration lives in `pyproject.toml` under `[tool.pyright]`.

## State Management

`AgentState` extends `MessagesState` with custom fields. Fields written concurrently during parallel fan-out use `Annotated` reducers for safe merging:

- `results` — `_merge_results` dict merge
- `metadata` — `_merge_results` dict merge
- `current_agent` — `_last_wins`
- `error` — `_last_wins`
