Metadata-Version: 2.5
Name: langchain-oneshot
Version: 0.16.0
Summary: LangChain tools for OneShot — 45 tools for AI agents
License-Expression: MIT
Requires-Python: >=3.10
Requires-Dist: langchain-core>=0.3.0
Requires-Dist: oneshot-python>=0.29.0
Requires-Dist: pydantic>=2.0
Provides-Extra: dev
Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Description-Content-Type: text/markdown

# langchain-oneshot

LangChain tools for [OneShot](https://oneshotagent.com) — commercial actions for AI agents.

Provides 45 tools as LangChain `BaseTool` subclasses with automatic x402 payment handling via USDC on Base.

## Installation

```bash
pip install langchain-oneshot
```

## Quick Start

```python
from langchain_oneshot import OneShotToolkit
from langchain_openai import ChatOpenAI
from langgraph.prebuilt import create_react_agent

toolkit = OneShotToolkit.from_private_key(
    private_key="0x...",
)

# Use all 45 tools with a LangGraph agent
tools = toolkit.get_tools()
llm = ChatOpenAI(model="gpt-4o")
agent = create_react_agent(llm, tools)

result = agent.invoke({
    "messages": [("user", "Research the latest AI agent frameworks")]
})
```

## Access-token sessions

Hosted agents can use prepaid credits without holding a wallet key:

```python
import os
from langchain_oneshot import OneShotToolkit

toolkit = OneShotToolkit.from_access_token(os.environ["ONESHOT_ACCESS_TOKEN"])
# Inside an async application:
# toolkit = await OneShotToolkit.afrom_access_token(os.environ["ONESHOT_ACCESS_TOKEN"])
tools = toolkit.get_tools()
```

Mint the token and set budgets from a wallet session. Token calls spend the agent's
credits and respect its stored caps; they cannot change budgets or manage tokens.
An insufficient balance raises `InsufficientCreditsError`. Fund credits from a wallet
with `OneShotClient.top_up_credits(amount)` and retry. See the
[hosted setup guide](https://docs.oneshotagent.com/sdk/remote-mcp).

## Individual Tools

```python
from langchain_oneshot import OneShotClient, ResearchTool

client = OneShotClient(private_key="0x...")
research = ResearchTool(client=client)
result = research.invoke({"topic": "AI agent frameworks 2026"})
```

## Available Tools

| Tool | Description |
|------|-------------|
| `oneshot_email` | Send emails |
| `oneshot_voice` | Make phone calls |
| `oneshot_sms` | Send SMS messages |
| `oneshot_research` | Deep web research |
| `oneshot_web_search` | Search the web |
| `oneshot_web_read` | Read a web page as markdown |
| `oneshot_people_search` | Search for people |
| `oneshot_enrich_profile` | Enrich a profile |
| `oneshot_find_email` | Find email address |
| `oneshot_verify_email` | Verify email |
| `oneshot_deep_research_person` | Full dossier on a person |
| `oneshot_social_profiles` | Find all social accounts |
| `oneshot_article_search` | Find articles about a person |
| `oneshot_person_newsfeed` | Recent social posts |
| `oneshot_person_interests` | Analyze interests |
| `oneshot_person_interactions` | Map followers/following |
| `oneshot_commerce_search` | Search products |
| `oneshot_commerce_buy` | Purchase product |
| `oneshot_build` | Build a website |
| `oneshot_update_build` | Update a website |
| `oneshot_browser` | Browser automation task |
| `oneshot_browser_create_profile` | Create a browser profile |
| `oneshot_browser_list_profiles` | List browser profiles |
| `oneshot_browser_delete_profile` | Delete a browser profile |
| `oneshot_inbox_list` | List inbox emails |
| `oneshot_inbox_get` | Get email by ID |
| `oneshot_sms_inbox_list` | List SMS inbox |
| `oneshot_sms_inbox_get` | Get SMS by ID |
| `oneshot_notifications` | List notifications |
| `oneshot_mark_notification_read` | Mark read |
| `oneshot_get_balance` | USDC balance |
| `oneshot_budget_status` | Today's spend vs the configured budget (read-only) |
| `oneshot_linkedin_connect` | Hosted login link for a human to connect their LinkedIn account (free) |
| `oneshot_linkedin_accounts` | Connected LinkedIn accounts / pending connection status (free) |
| `oneshot_linkedin_sync` | One bounded, resumable LinkedIn history-sync run (paid) |
| `oneshot_linkedin_conversations` | Synced LinkedIn conversations with coverage state (free) |
| `oneshot_linkedin_messages` | Synced LinkedIn messages, filterable by direction / since (free) |
| `oneshot_linkedin_reply` | Send a reply through the connected account (paid, idempotent) |
| `oneshot_linkedin_view_profile` | View a profile through the connected account (paid) |
| `oneshot_linkedin_react` | React to a post through the connected account (paid) |
| `oneshot_list_domains` | Sending domains + reputation/rotation state |
| `oneshot_pause_domain` | Take a domain out of rotation |
| `oneshot_resume_domain` | Put a paused domain back into rotation |

Paid tools are priced in USDC via x402. See [Pricing](https://docs.oneshotagent.com/pricing) for current rates.

## How Payments Work

Paid tools use the [x402 protocol](https://x402.org). When a tool requires payment:

1. The client POSTs to the tool endpoint
2. The API returns `402 Payment Required` with a quote
3. The client signs a USDC `TransferWithAuthorization` (EIP-3009) using your private key
4. The client re-POSTs with the signed payment header
5. The API processes the request and returns the result

All payment signing happens locally — your private key never leaves your machine.

Read tools (inbox, SMS inbox, notifications, balance, browser profiles) additionally send a signed **EIP-712 read proof** (`x-agent-proof`) so the API can verify you control the `X-Agent-ID` wallet before returning private data. This is handled by the underlying `oneshot-python` client — no extra code. Requires `oneshot-python >= 0.18.0` (already the dependency floor).

## Configuration

```python
toolkit = OneShotToolkit.from_private_key("0x...")

# Custom API URL
toolkit = OneShotToolkit.from_private_key("0x...", base_url="https://custom-api.example.com")
```

The SDK operates on **Base Mainnet** with real USDC. Fund your wallet before making paid tool calls.

### Spend budget

```python
toolkit = OneShotToolkit.from_private_key(
    "0x...",
    budgets={"daily": 50, "per_transaction": 5, "alert_at": 0.8},
    alert_email="you@example.com",
)
```

Enforced server-side on every paid call (`403 budget_exceeded` → `oneshot.BudgetExceededError`). The agent can read its utilization with `oneshot_budget_status` but cannot change the cap. Requires `oneshot-python >= 0.20.0`.

## Requirements

- Python 3.10+
- `langchain-core >= 0.3.0`
- `oneshot-python >= 0.18.0`
- `pydantic >= 2.0`

## Links

- [Documentation](https://docs.oneshotagent.com/sdk/langchain)
- [oneshot-python on PyPI](https://pypi.org/project/oneshot-python/) — Core HTTP client (dependency)
- [TypeScript SDK](https://www.npmjs.com/package/@oneshot-agent/sdk)
- [MCP Server](https://www.npmjs.com/package/@oneshot-agent/mcp-server)
- [GitHub](https://github.com/oneshot-agent/sdk)

## License

MIT

### LinkedIn connection recovery

If the active account list is empty or an account is `deleted_upstream` or
`revoked`, ask the human to use `oneshot_linkedin_connect` and authorize fresh
grants. An existing account with `reconnect_required` needs reconnect through
the owning application. Reconnect and revoke are intentionally not agent tools.
Do not automatically create a new connection in response to authentication
failures or timeouts.
