Metadata-Version: 2.4
Name: xat-langchain
Version: 0.1.0
Summary: XAT signing for LangChain -- every tool call gets an Agent-Signature header. OpenAPI x-agent-trust.
Author-email: Raza Sharif <raza@cybersecai.co.uk>
License: Apache-2.0
Project-URL: Homepage, https://spec.openapis.org/registry/extension/x-agent-trust.html
Project-URL: Repository, https://github.com/razashariff/xat-langchain
Project-URL: Documentation, https://x-agent-auth.fly.dev/integrate
Keywords: xat,x-agent-trust,langchain,agent,ai-agent,security,signing,openapi
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Security
Classifier: Topic :: Software Development :: Libraries
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Requires-Dist: cryptography>=41.0
Requires-Dist: requests>=2.28
Requires-Dist: langchain-core>=0.2

# xat-langchain

XAT signing for LangChain. Every tool call gets an `Agent-Signature` header.

Based on the [`x-agent-trust`](https://spec.openapis.org/registry/extension/x-agent-trust.html) extension in the OpenAPI Extensions Registry.

## Install

```bash
pip install xat-langchain
```

## Usage

### Wrap existing tools

```python
from xat_langchain import XATToolkit

toolkit = XATToolkit(key_file="agent.pem", agent_id="my-agent")
signed_tools = toolkit.wrap(existing_tools)

# Every HTTP call these tools make now carries Agent-Signature
agent = create_react_agent(llm, signed_tools)
```

### Decorator

```python
from xat_langchain import xat_tool
import requests

@xat_tool(key_file="agent.pem", agent_id="my-agent")
def search(query: str) -> str:
    return requests.get(f"https://api.example.com/search?q={query}").text
```

### With AWS KMS (production)

```python
import boto3

kms = boto3.client("kms", region_name="eu-west-2")

async def kms_sign(data: bytes) -> bytes:
    import hashlib
    digest = hashlib.sha256(data).digest()
    response = kms.sign(
        KeyId="arn:aws:kms:eu-west-2:123456:key/abcd",
        Message=digest,
        MessageType="DIGEST",
        SigningAlgorithm="ECDSA_SHA_256"
    )
    return response["Signature"]

toolkit = XATToolkit(kms_sign=kms_sign, agent_id="prod-agent")
```

### Audit trail

```python
from xat_langchain import XATCallbackHandler

handler = XATCallbackHandler()
agent.invoke({"input": "..."}, config={"callbacks": [handler]})
print(handler.signed_calls)
```

## What it does

- Wraps LangChain tool HTTP calls with automatic `Agent-Signature` signing
- ECDSA P-256 (ES256) over a canonical request string
- Private key never enters memory when using KMS providers
- Works with any LangChain tool that makes HTTP requests

## Links

- [OpenAPI Extensions Registry](https://spec.openapis.org/registry/extension/x-agent-trust.html)
- [Integration guide](https://x-agent-auth.fly.dev/integrate)
- [XAT Node.js library](https://www.npmjs.com/package/xat-agent)
- [Spectral linter](https://www.npmjs.com/package/spectral-x-agent-trust)

## Author

Raza Sharif, [CyberSecAI Ltd](https://cybersecai.co.uk)

## License

Apache-2.0
