Metadata-Version: 2.4
Name: aiyoplane-openai-agents
Version: 1.0.0
Summary: AEAP Composition Boundary Adapter for the OpenAI Agents SDK. Thin wrapper that attaches the Runtime Decision Point to agent tool invocations.
Author-email: "Aiyoplane, Inc." <rashon@aiyoplane.com>
License: Apache-2.0
Project-URL: Homepage, https://aiyoplane.com
Project-URL: Documentation, https://github.com/aiyoplane/openai-agents-python
Project-URL: Repository, https://github.com/aiyoplane/openai-agents-python
Project-URL: Issues, https://github.com/aiyoplane/openai-agents-python/issues
Project-URL: Trust Surface, https://aiyoplane.com/trust
Project-URL: AEAP Specification, https://github.com/aiyoplane/aeap
Keywords: aiyo,aiyoplane,aeap,openai,openai-agents,agents-sdk,authorization,runtime-decision-point,rdp,execution-receipt,composition-boundary,agent-authorization,function-tool,guardrails
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Security
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
License-File: NOTICE
Requires-Dist: aiyoplane-mcp-authz>=1.0.1
Requires-Dist: openai-agents>=0.0.1
Provides-Extra: test
Requires-Dist: pytest>=7.0; extra == "test"
Requires-Dist: pytest-asyncio>=0.21; extra == "test"
Dynamic: license-file

# aiyoplane-openai-agents

**AEAP Composition Boundary Adapter for the OpenAI Agents SDK.**

A thin wrapper that attaches the AEAP Runtime Decision Point (RDP) to the OpenAI Agents SDK's function-tool invocation surface. Consequential tool executions produce independently verifiable Execution Receipts. The adapter composes with the Agents SDK's own guardrails, handoffs, and session machinery — it does not replace any of them.

```bash
pip install aiyoplane-openai-agents
```

## What this adapter is (and is not)

**It is:** the shape AEAP takes when attached to an OpenAI Agents SDK function tool. The underlying authorization logic lives in [`aiyoplane-mcp-authz`](https://pypi.org/project/aiyoplane-mcp-authz/); this package distributes that logic into the Agents SDK ecosystem.

**It is not:** a replacement for Agents SDK guardrails. Guardrails are the SDK's own input/output filter mechanism; AEAP is a protocol-level authorization decision at the Composition Boundary. The two compose: an Agents guardrail can short-circuit on input shape; AEAP decides whether the policy-governed consequential action may execute at all.

See the [AEAP specification](https://github.com/aiyoplane/aeap) §9 for the Composition Boundary primitive this adapter realizes.

## Minimal usage

```python
from agents import Agent, function_tool
from aiyoplane_mcp_authz import create_aiyo_mcp_authz, create_local_rdp
from aiyoplane_openai_agents import aiyo_tool, BlockedByPolicy, EscalationRequired

policy = {
    "rules": [
        {"action_type": "payment", "amount_max": 1_000, "effect": "allow"},
        {"action_type": "payment", "amount_max": 10_000, "effect": "escalate"},
        {"action_type": "payment", "effect": "block"},
    ]
}

authz = create_aiyo_mcp_authz(
    rdp=create_local_rdp(policy=policy),
    tool_config={
        "transfer_funds": {
            "aiyo_gated": True,
            "action": {"type": "payment"},
        },
    },
)

# Decorator order matters: @aiyo_tool BEFORE @function_tool.
@function_tool
@aiyo_tool(
    authz=authz,
    tool_name="transfer_funds",
    intent_builder=lambda kwargs: {
        "type": "payment",
        "amount": kwargs["amount"],
        "target": kwargs["to_account"],
    },
)
def transfer_funds(amount: int, to_account: str) -> str:
    """Transfer funds between accounts."""
    return actually_transfer(amount, to_account)

# Register with your Agent the usual way:
banker = Agent(
    name="banker",
    instructions="Help the user manage their accounts.",
    tools=[transfer_funds],
)
```

## Decorator order — important

Apply `@aiyo_tool` **first** (closest to the function), then `@function_tool`:

```python
@function_tool        # OUTER — converts the gated callable into an Agents SDK tool
@aiyo_tool(...)       # INNER — wraps the function with the AEAP gate
def my_tool(...):
    ...
```

This order ensures the AEAP gate runs before the Agents SDK invokes the function. Reversing the order means `function_tool` wraps the raw function first and the AEAP gate never fires.

## Function form

If the function is defined elsewhere and you can't use decorators:

```python
from aiyoplane_openai_agents import wrap_function_tool

def transfer_funds(amount: int, to_account: str) -> str:
    return actually_transfer(amount, to_account)

guarded = wrap_function_tool(
    transfer_funds,
    authz=authz,
    tool_name="transfer_funds",
    intent_builder=lambda kwargs: {"type": "payment", "amount": kwargs["amount"]},
)

# Pass guarded through @function_tool manually:
from agents import function_tool
agent_tool = function_tool(guarded)
```

## Composition Boundary — what the adapter actually does

For each wrapped tool invocation:

1. **Intent construction.** `intent_builder(kwargs)` produces an AEAP Intent payload.
2. **RDP evaluation.** The Intent is passed to `aiyoplane-mcp-authz`'s AiyoAuthz middleware.
3. **Verdict composition.**
   - **ALLOW** → the inner function runs with the original kwargs. On `attach_receipt=True`, returns `{"result": ..., "aeap_receipt": ...}`.
   - **ESCALATE** → `EscalationRequired` is raised with an `escalation_id`.
   - **BLOCK** → `BlockedByPolicy` is raised; the function never executes.
4. **Fail-closed default.** Any ambiguous condition — missing `intent_builder`, non-dict Intent, RDP unreachable, misconfigured `tool_config` — results in `BlockedByPolicy`.

## Composing with Agents SDK guardrails

AEAP and Agents SDK guardrails are complementary:

```python
from agents import Agent, function_tool, input_guardrail

@input_guardrail
async def validate_shape(ctx, agent, input_data):
    # Guardrail: cheap input-shape check (SDK-native).
    return not malformed(input_data)

@function_tool
@aiyo_tool(authz=authz, tool_name="transfer_funds", intent_builder=...)
def transfer_funds(amount: int, to_account: str) -> str:
    return actually_transfer(amount, to_account)

agent = Agent(
    name="banker",
    tools=[transfer_funds],
    input_guardrails=[validate_shape],
)
```

The guardrail runs on input shape; the AEAP gate runs on policy evaluation at the tool-invocation boundary. Different layers, both valuable.

## Local vs. hosted RDP

```python
from aiyoplane_mcp_authz import create_local_rdp, create_hosted_rdp

# Development:
authz = create_aiyo_mcp_authz(rdp=create_local_rdp(policy=policy), tool_config={...})

# Production:
authz = create_aiyo_mcp_authz(
    rdp=create_hosted_rdp(api_key="aiyo_live_..."),
    tool_config={...},
)
```

## API reference

### `aiyo_tool(*, authz, tool_name, intent_builder, attach_receipt=False)`

Decorator form. Returns a decorator that wraps a function with an AEAP gate.

### `wrap_function_tool(fn, *, authz, tool_name, intent_builder, attach_receipt=False)`

Function form. Equivalent to applying `aiyo_tool(...)` as a decorator.

### Exceptions

- `AiyoOpenAIAgentsError` — base class
- `AdapterConfigError` — adapter configuration is invalid
- `BlockedByPolicy` — RDP returned BLOCK; the tool did not execute
- `EscalationRequired` — RDP returned ESCALATE; the tool call is held pending resolution

## License

Apache License 2.0.

## Links

- **AEAP specification:** https://github.com/aiyoplane/aeap
- **Underlying implementation:** [`aiyoplane-mcp-authz`](https://pypi.org/project/aiyoplane-mcp-authz/)
- **Node sibling:** `@aiyoplane/openai-agents` on npm
- **Trust surface:** https://aiyoplane.com/trust
- **Issues:** https://github.com/aiyoplane/openai-agents-python/issues

OpenAI and the OpenAI Agents SDK are trademarks of OpenAI, Inc. This package is an independent AEAP Composition Boundary Adapter and is not affiliated with or endorsed by OpenAI, Inc.

**Verify First. Execute Second.**
