Metadata-Version: 2.4
Name: context-fabric-ai
Version: 0.1.0
Summary: Semantic context propagation protocol between heterogeneous AI agent frameworks
Project-URL: Homepage, https://github.com/shubhamdusane/context-fabric
Project-URL: Repository, https://github.com/shubhamdusane/context-fabric
Author-email: Shubham Dusane <sdusane4@gmail.com>
License: Apache-2.0
License-File: LICENSE
Keywords: ai-agents,autogen,context-propagation,langchain,mcp,multi-agent
Classifier: Development Status :: 3 - Alpha
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Requires-Python: >=3.10
Provides-Extra: all
Requires-Dist: redis>=5.0.0; extra == 'all'
Provides-Extra: dev
Requires-Dist: build>=1.2.0; extra == 'dev'
Requires-Dist: pytest>=8.0.0; extra == 'dev'
Requires-Dist: ruff>=0.5.0; extra == 'dev'
Requires-Dist: twine>=5.0.0; extra == 'dev'
Provides-Extra: redis
Requires-Dist: redis>=5.0.0; extra == 'redis'
Provides-Extra: test
Requires-Dist: pytest>=8.0.0; extra == 'test'
Description-Content-Type: text/markdown

# context-fabric

[![Tests](https://img.shields.io/badge/tests-19%20passing-brightgreen)]()
[![Python](https://img.shields.io/badge/python-3.10+-blue)](https://www.python.org/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)

**A semantic context propagation protocol between heterogeneous AI agent frameworks.**

---

## Table of Contents

- [What is context-fabric?](#what-is-context-fabric)
- [The Problem](#the-problem)
- [How It Works](#how-it-works)
- [Installation](#installation)
- [Quick Start](#quick-start)
- [Python API Reference](#python-api-reference)
- [Framework Adapters](#framework-adapters)
- [Privacy & PII Handling](#privacy--pii-handling)
- [Architecture](#architecture)
- [Contributing](#contributing)
- [Roadmap](#roadmap)
- [License](#license)

---

## What is context-fabric?

context-fabric is a lightweight protocol layer that enables AI agents built on different frameworks—LangChain, AutoGen, OpenAI, and others—to share rich, structured context seamlessly.

Think of it as **USB for AI agents**. Just as a USB cable lets devices from different manufacturers communicate, context-fabric lets agents from different ecosystems exchange task state, memory, tool results, and metadata without writing custom glue code for each pair of frameworks.

### Key Concepts

| Concept | Description |
|---|---|
| **ContextEnvelope** | A standardized, serializable container for carrying context data between agents. |
| **ContextFabric** | The central orchestrator that routes envelopes between adapters. |
| **Adapters** | Framework-specific connectors that translate between native formats and the ContextEnvelope standard. |
| **strip_private()** | A built-in utility for scrubbing personally identifiable information (PII) from envelopes before cross-boundary transfers. |

---

## The Problem

Modern AI agent systems rarely live in a single framework. A production pipeline might combine:

- A **LangChain** retrieval chain for document Q&A
- An **AutoGen** multi-agent debate loop for reasoning
- A **raw OpenAI API** call for final synthesis

Each framework has its own internal state format, memory abstraction, and message protocol. When you need Agent A (LangChain) to hand off context to Agent B (AutoGen), you face:

```
Framework A                          Framework B
┌─────────────────┐                  ┌─────────────────┐
│ LangChain       │   ???            │ AutoGen         │
│ Message History │ ──────────────>  │ Chat History    │
│ Retriever State │   manual         │ Agent State     │
│ Tool Outputs    │   mapping        │ Tool Calls      │
└─────────────────┘                  └─────────────────┘
```

**The result:** brittle, hand-written serializers that break when either framework updates. context-fabric eliminates this by introducing a shared, framework-agnostic context layer.

---

## How It Works

### Context Propagation Flow

```
┌──────────────┐       ┌──────────────────┐       ┌──────────────┐
│   Source      │       │   ContextFabric   │       │   Target     │
│   Agent      │       │   (Router)        │       │   Agent      │
└──────┬───────┘       └────────┬─────────┘       └──────┬───────┘
       │                        │                         │
       │  1. native state       │                         │
       │ ─────────────────────> │                         │
       │                        │  2. ContextEnvelope     │
       │                        │     (normalized)        │
       │                        │ ─────────────────────>  │
       │                        │                         │
       │                        │  3. native state        │
       │                        │     (adapted)           │
       │                        │ <─────────────────────  │
```

### Under the Hood

1. **Outbound Adapter** reads the source framework's native state and populates a `ContextEnvelope`.
2. **ContextFabric** optionally applies transforms (PII stripping, enrichment, routing rules).
3. **Inbound Adapter** unpacks the envelope into the target framework's native format.

```
Source Framework         Adapter Layer          ContextEnvelope
┌────────────────┐      ┌────────────┐      ┌─────────────────┐
│ LangChain      │─────>│ langchain_ │─────>│                 │
│ Messages,      │      │ adapter    │      │  task_id        │
│ Retriever,     │      └────────────┘      │  messages[]     │
│ Tools          │                          │  metadata{}     │
└────────────────┘                          │  tool_results[] │
                                            │  memory{}       │
                                            └─────────────────┘
                                                  │
                                                  ▼
Target Framework         Adapter Layer          ContextEnvelope
┌────────────────┐      ┌────────────┐           │
│ AutoGen        │<─────│ autogen_   │<──────────┘
│ AgentChat,     │      │ adapter    │
│ ToolCalls      │      └────────────┘
└────────────────┘
```

---

## Installation

```bash
pip install context-fabric
```

Or from source:

```bash
git clone https://github.com/your-org/context-fabric.git
cd context-fabric
pip install -e .
```

### Requirements

- Python 3.10+
- No external dependencies for core functionality (adapters have optional extras)

```bash
# Install with specific adapter support
pip install context-fabric[langchain]
pip install context-fabric[autogen]
pip install context-fabric[openai]
pip install context-fabric[all]
```

---

## Quick Start

### 1. Create and send an envelope

```python
from context_fabric import ContextFabric, ContextEnvelope

# Build an envelope with task context
envelope = ContextEnvelope(
    task_id="summarize-doc-42",
    messages=[
        {"role": "user", "content": "Summarize the quarterly report"},
        {"role": "assistant", "content": "Retrieving document..."},
    ],
    metadata={"source_framework": "langchain", "target_framework": "openai"},
    tool_results=[{"tool": "retriever", "output": "Q3 revenue: $4.2M"}],
)

# Send through the fabric
fabric = ContextFabric()
result = fabric.route(envelope)
```

### 2. Use adapters for framework interop

```python
from context_fabric.adapters import LangChainAdapter, OpenAIAdapter

# Wrap a LangChain agent's state
lc_adapter = LangChainAdapter()
envelope = lc_adapter.export(lc_agent_state)

# Import into OpenAI-compatible format
openai_adapter = OpenAIAdapter()
openai_messages = openai_adapter.import_envelope(envelope)
```

### 3. Strip PII before cross-boundary transfer

```python
from context_fabric import ContextEnvelope, strip_private

envelope = ContextEnvelope(
    task_id="customer-support-99",
    messages=[
        {"role": "user", "content": "My name is John Doe, SSN 123-45-6789"},
    ],
    metadata={"customer_id": "CUST-42"},
)

clean = strip_private(envelope)
# PII fields are redacted
```

---

## Python API Reference

### `ContextEnvelope`

The core data container for all context passing.

```python
ContextEnvelope(
    task_id: str,                           # Unique identifier for the task
    messages: list[dict],                   # Conversation / action history
    metadata: dict = {},                    # Arbitrary key-value pairs
    tool_results: list[dict] = [],          # Outputs from tool invocations
    memory: dict = {},                      # Persistent memory store
    parent_id: str | None = None,           # Link to parent envelope (chaining)
)
```

**Methods:**

| Method | Returns | Description |
|---|---|---|
| `to_dict()` | `dict` | Serialize to a plain dictionary |
| `to_json()` | `str` | Serialize to JSON string |
| `from_dict(data)` | `ContextEnvelope` | Deserialize from a dictionary |
| `from_json(json_str)` | `ContextEnvelope` | Deserialize from a JSON string |
| `clone()` | `ContextEnvelope` | Deep copy of the envelope |
| `merge(other)` | `ContextEnvelope` | Merge another envelope's data into this one |
| `strip_private(keys)` | `ContextEnvelope` | Remove or redact specified keys (see Privacy) |

---

### `ContextFabric`

The routing and orchestration layer.

```python
fabric = ContextFabric()

fabric.route(envelope, target="openai")       # Route to a named adapter
fabric.register("my_framework", my_adapter)   # Register a custom adapter
fabric.add_transform(fn)                      # Add a pre-route transform
```

---

### `strip_private(envelope, **kwargs)`

Scrub PII from an envelope.

```python
from context_fabric import strip_private

# Default: strips common PII patterns (emails, SSNs, phone numbers)
clean = strip_private(envelope)

# Custom: specify exact keys to redact
clean = strip_private(envelope, keys=["customer_id", "ssn"])

# Custom: provide a redaction function
clean = strip_private(envelope, redactor=lambda val: "[REDACTED]")
```

---

## Framework Adapters

Adapters translate between framework-native state and `ContextEnvelope`.

### Built-in Adapters

| Adapter | Framework | Import |
|---|---|---|
| `LangChainAdapter` | LangChain | `context_fabric.adapters.LangChainAdapter` |
| `AutoGenAdapter` | AutoGen | `context_fabric.adapters.AutoGenAdapter` |
| `OpenAIAdapter` | OpenAI API | `context_fabric.adapters.OpenAIAdapter` |

### Adapter Interface

All adapters implement the same protocol:

```python
class BaseAdapter:
    def export(self, native_state) -> ContextEnvelope:
        """Convert framework state to a ContextEnvelope."""
        ...

    def import_envelope(self, envelope: ContextEnvelope):
        """Convert a ContextEnvelope back to framework-native state."""
        ...
```

### Writing a Custom Adapter

```python
from context_fabric.adapters import BaseAdapter
from context_fabric import ContextEnvelope

class MyFrameworkAdapter(BaseAdapter):
    def export(self, native_state) -> ContextEnvelope:
        return ContextEnvelope(
            task_id=native_state.id,
            messages=[{"role": m.role, "content": m.text} for m in native_state.history],
            metadata={"framework": "my_framework"},
        )

    def import_envelope(self, envelope: ContextEnvelope):
        from my_framework import AgentState, Message
        return AgentState(
            id=envelope.task_id,
            history=[Message(role=m["role"], text=m["content"]) for m in envelope.messages],
        )
```

Register it:

```python
fabric = ContextFabric()
fabric.register("my_framework", MyFrameworkAdapter())
```

---

## Privacy & PII Handling

Cross-framework context sharing raises privacy concerns. `strip_private()` provides built-in PII scrubbing.

### Default Behavior

```python
from context_fabric import strip_private

envelope = ContextEnvelope(
    task_id="task-1",
    messages=[
        {"role": "user", "content": "Contact me at john@example.com"},
    ],
)

clean = strip_private(envelope)
# Auto-detects and redacts emails, SSNs, phone numbers from string values
```

### Custom Scrubbing

```python
# Redact specific metadata keys
clean = strip_private(envelope, metadata_keys=["customer_id", "ip_address"])

# Redact from all message content using a regex
clean = strip_private(envelope, patterns=[r"\b\d{3}-\d{2}-\d{4}\b"])  # SSN pattern

# Full custom redactor
def my_redactor(value):
    if isinstance(value, str) and "secret" in value.lower():
        return "[REDACTED]"
    return value

clean = strip_private(envelope, redactor=my_redactor)
```

### PII Audit Logging

```python
from context_fabric import strip_private

clean = strip_private(envelope, audit=True)
# Returns (clean_envelope, audit_log) tuple
# audit_log contains list of redaction actions taken
```

---

## Architecture

```
context-fabric/
├── context_fabric/
│   ├── __init__.py              # Public API exports
│   ├── envelope.py              # ContextEnvelope dataclass
│   ├── fabric.py                # ContextFabric router
│   ├── transforms.py            # Built-in transforms (strip_private, etc.)
│   ├── adapters/
│   │   ├── __init__.py          # Adapter registry
│   │   ├── base.py              # BaseAdapter protocol
│   │   ├── langchain_adapter.py # LangChain integration
│   │   ├── autogen_adapter.py   # AutoGen integration
│   │   └── openai_adapter.py    # OpenAI API integration
│   └── utils/
│       ├── pii.py               # PII detection and redaction
│       └── serialization.py     # JSON/dict conversion helpers
├── tests/
│   ├── test_envelope.py         # Envelope serialization tests
│   ├── test_fabric.py           # Routing and adapter tests
│   ├── test_adapters/           # Per-framework adapter tests
│   └── test_privacy.py          # PII stripping tests
├── pyproject.toml
├── LICENSE
└── README.md
```

### Design Principles

1. **Zero external dependencies** for core protocol—adapters are optional extras.
2. **Framework-agnostic envelope format**—plain dicts and lists, no custom classes inside messages.
3. **Adapter symmetry**—every adapter can both export and import, enabling round-trips.
4. **Privacy by default**—`strip_private()` is a first-class citizen, not an afterthought.
5. **Immutable envelopes**—methods like `clone()` and `merge()` return new instances.

---

## Contributing

Contributions are welcome! Here's how to get started:

```bash
git clone https://github.com/your-org/context-fabric.git
cd context-fabric
python -m venv .venv
.venv\Scripts\activate        # Windows
# source .venv/bin/activate   # macOS/Linux
pip install -e ".[dev]"
pytest                        # All 19 tests should pass
```

### Guidelines

- **Adapters** should implement both `export()` and `import_envelope()` with round-trip fidelity.
- **Tests** are required for all new adapters and transforms.
- **PII patterns** should be contributed as regex patterns in `utils/pii.py`.
- **No new dependencies** in core—keep the protocol lightweight.

### Running Tests

```bash
pytest                        # Run all tests
pytest tests/test_privacy.py  # Privacy-specific tests
pytest -v                     # Verbose output
```

---

## Roadmap

| Phase | Feature | Status |
|---|---|---|
| **v0.1** | Core protocol, ContextEnvelope, ContextFabric | ✅ Done |
| **v0.1** | LangChain, AutoGen, OpenAI adapters | ✅ Done |
| **v0.1** | `strip_private()` PII scrubbing | ✅ Done |
| **v0.1** | 19 passing tests | ✅ Done |
| **v0.2** | Streaming envelope support (chunked context) | 🔜 Planned |
| **v0.2** | Async adapter protocol (`async export/import`) | 🔜 Planned |
| **v0.2** | LlamaIndex adapter | 🔜 Planned |
| **v0.3** | Context versioning and conflict resolution | 📋 Planned |
| **v0.3** | Envelope compression for large payloads | 📋 Planned |
| **v0.3** | gRPC transport layer | 📋 Planned |
| **v1.0** | Stable protocol specification | 🎯 Goal |

---

## License

MIT License. See [LICENSE](LICENSE) for details.

---

<p align="center">
  <sub>Built with care for the multi-framework AI agent ecosystem.</sub>
</p>
