Metadata-Version: 2.4
Name: outsail-langchain
Version: 0.1.0
Summary: LangChain and LangGraph integration for the Outsail Context Intelligence Platform
Author: Outsail
License: MIT
Project-URL: Homepage, https://outsail.theatomicshift.com
Project-URL: Repository, https://github.com/theatomicshift/outsail
Project-URL: Documentation, https://outsail.theatomicshift.com/docs
Keywords: outsail,ai,agents,research,context-intelligence,langchain,langgraph
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: outsail-sdk>=0.28.1
Requires-Dist: langchain-core>=0.3.0
Requires-Dist: langgraph>=0.2.0
Requires-Dist: pydantic>=2.0.0
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.24.0; extra == "dev"
Requires-Dist: pytest-cov>=5.0; extra == "dev"
Dynamic: license-file

# Outsail LangChain / LangGraph Integration (Python)

Thin adapter package that exposes Outsail's curated Capability Registry tools
for [LangChain](https://github.com/langchain-ai/langchain) and
[LangGraph](https://github.com/langchain-ai/langgraph) Python applications.

## Installation

```bash
pip install outsail outsail-langchain
```

## Usage

### LangChain Tools

```python
from outsail import OutsailClient
from outsail_langchain import OutsailToolkit
from langgraph.prebuilt import ToolNode

async with OutsailClient(
    api_key="osk_live_...",
) as client:
    toolkit = OutsailToolkit(client)
    tools = toolkit.get_tools(profiles=["research", "read_only"])

    # Use with LangGraph ToolNode
    tool_node = ToolNode(tools)
```

### LangGraph Research Node

```python
from outsail import OutsailClient
from outsail_langchain import create_outsail_research_node
from langgraph.graph import StateGraph

async with OutsailClient(
    api_key="osk_live_...",
) as client:
    builder = StateGraph(MyState)
    builder.add_node("research", create_outsail_research_node(client))
    builder.set_entry_point("research")
```

## Available Tools

All 17 curated agent-safe capabilities are exposed as LangChain tools,
organised into three profiles:

### Research Profile
- `outsail_research_start` — Start an asynchronous research job
- `outsail_research_status` — Poll research job status and results
- `outsail_verify` — Verify a claim with traceable evidence
- `outsail_compare` — Compare multiple source sets

### Read-only Profile
- `outsail_context_pack_get` — Retrieve a Context Pack by ID
- `outsail_agent_context_get` — Retrieve agent-shaped context
- `outsail_extract` — Extract clean text from a URL
- `outsail_map` — Create a site map of a website
- `outsail_report` — Generate a research report in Markdown
- `outsail_decision_report` — Generate a decision-ready report
- `outsail_discover` — Discover relevant sources

### Monitoring Profile
- `outsail_monitor_list` — List all source monitors
- `outsail_monitor_get` — Get monitor details
- `outsail_monitor_create` — Create a source monitor
- `outsail_monitor_run` — Trigger a monitor check
- `outsail_monitor_pause` — Pause a monitor
- `outsail_monitor_resume` — Resume a monitor

## API Reference

### `OutsailToolkit`

```python
class OutsailToolkit:
    def __init__(self, client: OutsailClient): ...

    def get_tools(
        self,
        *,
        profiles: Sequence[Literal["research", "read_only", "monitoring"]] | None = None,
    ) -> list[StructuredTool]: ...
```

### `create_outsail_tools`

```python
def create_outsail_tools(
    client: OutsailClient,
    *,
    profiles: Sequence[ToolProfile] | None = None,
) -> list[StructuredTool]: ...
```

### `create_outsail_research_node`

```python
def create_outsail_research_node(
    client: OutsailClient,
    *,
    poll_interval_ms: int = 2000,
    timeout_ms: int = 300_000,
    emit_progress: bool = True,
) -> Callable[[dict[str, Any]], dict[str, Any]]: ...
```

## State Contract (Research Node)

**Input state keys:**
- `research_objective` (str, required) — Research objective or question
- `research_urls` (list[str], optional) — Specific URLs to include
- `research_discover` (bool, optional) — Auto-discover sources (default: True)
- `research_profile` (str, optional) — Research profile
- `research_depth` (int, optional) — 0 = fast, 1 = deep

**Output state patch:**
- `context_pack_id` (str | None) — Completed Context Pack ID
- `research_status` ("completed" | "failed" | "timeout")
- `research_error` (str | None) — Error message if failed
- `research_job_id` (str | None) — The job ID

## Development

```bash
# Install in editable mode with dev dependencies
pip install -e ".[dev]"

# Run tests
pytest

# Run tests with coverage
pytest --cov=outsail_langchain
```

## License

MIT
