> ## Documentation Index
> Fetch the complete documentation index at: https://docs.qwedai.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Open Responses

> Intercept and verify LLM tool calls in agentic loops with QWED-Finance. OpenAI-compatible tool schemas and verified results with cryptographic receipts.

## Quick start

```python theme={null}
from qwed_finance import OpenResponsesIntegration

qwed = OpenResponsesIntegration()

# Get OpenAI-compatible tools schema
tools = qwed.get_tools_schema()

# Handle tool call from LLM
result = qwed.handle_tool_call(
    tool_name="calculate_npv",
    arguments={"cashflows": [-1000, 300, 400], "rate": 0.1}
)

print(result.status)  # ToolCallStatus.COMPUTED
print(result.result)  # {"npv": "$180.42", "verified": False, "computed": True, ...}
```

<Warning>
  Built-in tool calls (NPV, loan, AML, options) return `ToolCallStatus.COMPUTED` — meaning the result was computed deterministically but **not** verified against an LLM claim. Only tools with a custom `verification_fn` that compare against an LLM output can return `ToolCallStatus.APPROVED`.
</Warning>

***

## Fail-closed default

<Note>
  **Since v2.1.0:** Tools registered without a `verification_fn` are **rejected by default**. This enforces the QWED principle: *"Verification decides IF."*
</Note>

```python theme={null}
# ❌ This tool will be REJECTED — no verification function
qwed.register_tool(
    name="transfer_funds",
    description="Transfer money",
    parameters={"amount": {"type": "number"}},
    # Missing verification_fn!
)

result = qwed.handle_tool_call("transfer_funds", {"amount": 999})
# result.status == ToolCallStatus.REJECTED
# result.error == "No verification function registered..."
# result.receipt is not None (rejection is audited)
```

***

## Tool call statuses

| Status     | Meaning                                                | `verified` in output |
| ---------- | ------------------------------------------------------ | -------------------- |
| `APPROVED` | Verified against LLM claim and passed                  | `true`               |
| `COMPUTED` | Computed deterministically, NOT compared to LLM claim  | `false`              |
| `REJECTED` | Verification failed or no `verification_fn` registered | N/A (error)          |
| `MODIFIED` | Arguments were corrected before approval               | `true`               |
| `ERROR`    | System error prevented verification                    | N/A (error)          |

***

## Tool call flow

```text theme={null}
┌─────────────┐     ┌─────────────┐     ┌─────────────────┐
│    LLM       │────▶│    QWED     │────▶│  Verified Result │
│  Tool Call   │     │  Intercept  │     │  (with receipt)  │
└─────────────┘     └─────────────┘     └─────────────────┘
                          │
                  Has verification_fn?
                    ╱           ╲
                  YES            NO
                   │              │
              Execute fn      REJECTED
              (try/except)    (audited)
                   │
            Return result
         APPROVED / COMPUTED
```

1. LLM emits tool call with arguments
2. QWED intercepts and checks for a registered `verification_fn`
3. If no `verification_fn` → **REJECTED** (fail-closed, audited)
4. If `verification_fn` exists → execute with error boundary
5. Returns verified result with cryptographic receipt

***

## Available built-in tools

| Tool                     | Description           | Engine   | Status     |
| ------------------------ | --------------------- | -------- | ---------- |
| `calculate_npv`          | Net Present Value     | SymPy    | `COMPUTED` |
| `calculate_loan_payment` | Monthly loan payment  | SymPy    | `COMPUTED` |
| `check_aml_compliance`   | AML threshold check   | Z3       | `COMPUTED` |
| `price_option`           | Black-Scholes pricing | Calculus | `COMPUTED` |

<Info>
  All built-in tools return `COMPUTED` status because they perform deterministic calculations without comparing against an LLM claim.
</Info>

### AML country consistency

The `check_aml_compliance` tool delegates to `ComplianceGuard.high_risk_countries` for its sanctions list, ensuring a **single source of truth** across the entire QWED-Finance system.

### Black-Scholes input validation

The `price_option` tool rejects non-positive inputs for `spot_price`, `strike_price`, `time_to_expiry`, and `volatility` before computing, preventing `ZeroDivisionError` at the math boundary.

### Black-Scholes single source of truth

<Note>
  **Since N-01 fix:** `price_option` delegates to `DerivativesGuard.verify_black_scholes()` — the same `mpmath` (30 dp) implementation used by direct guard calls. This guarantees that pricing through the OpenResponses integration and pricing through `DerivativesGuard` produce **identical** outputs for identical inputs.
</Note>

Previously, the integration shipped its own IEEE-754 `float`-based Black-Scholes routine (`math.log/exp/sqrt/erf`). Same formula, two precision paths — same input could yield two different outputs depending on call site. The duplicate has been removed.

The tool result now reports the computed price and `delta` Greek straight from the guard's quantized `Decimal` output:

```python theme={null}
result = qwed.handle_tool_call("price_option", {
    "spot_price": 100,
    "strike_price": 100,
    "time_to_expiry": 1.0,
    "risk_free_rate": 0.05,
    "volatility": 0.2,
    "option_type": "call",
})

print(result.result["price"])  # e.g. "$10.4506" — mpmath, deterministic
print(result.result["delta"])  # e.g. "0.6368" — Decimal-quantized string
```

***

## Item wrapper (streaming)

Format results for streaming compatibility:

```python theme={null}
# Handle tool call
result = qwed.handle_tool_call("calculate_npv", args)

# Format as Open Responses Item
item = qwed.format_for_responses_api(result, tool_call_id="call_abc123")
```

### COMPUTED item structure

```json theme={null}
{
  "type": "tool_result",
  "id": "call_abc123",
  "tool_use_id": "calculate_npv",
  "content": {
    "mime_type": "application/json",
    "text": "{\"result\": {\"npv\": \"$180.42\"}, \"verification\": {\"status\": \"computed_only\", \"verified\": false, \"note\": \"Result was computed deterministically but NOT verified against an LLM claim.\", \"engine\": \"SymPy\", \"receipt_id\": \"abc-123\", \"input_hash\": \"...\"}}"
  },
  "is_error": false
}
```

### APPROVED item structure

```json theme={null}
{
  "type": "tool_result",
  "id": "call_abc123",
  "tool_use_id": "my_custom_tool",
  "content": {
    "mime_type": "application/json",
    "text": "{\"result\": {...}, \"verification\": {\"status\": \"verified\", \"verified\": true, \"engine\": \"Z3\", \"receipt_id\": \"def-456\", \"input_hash\": \"...\"}}"
  },
  "is_error": false
}
```

***

## OpenAI integration

```python theme={null}
from openai import OpenAI

client = OpenAI()
qwed = OpenResponsesIntegration()

response = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "Calculate NPV of $1000 investment"}],
    tools=qwed.get_tools_schema(),  # QWED verified tools
    tool_choice="auto"
)

# Intercept and verify tool calls
for tool_call in response.choices[0].message.tool_calls:
    verified = qwed.handle_tool_call(
        tool_call.function.name,
        tool_call.function.arguments
    )
    
    if verified.status == ToolCallStatus.COMPUTED:
        print(f"Computed: {verified.result}")
    elif verified.status == ToolCallStatus.APPROVED:
        print(f"Verified: {verified.result}")
    else:
        print(f"Failed: {verified.error}")
```

***

## Custom tools

Register your own verified tools. A `verification_fn` is **required** — tools without one are rejected.

```python theme={null}
from qwed_finance import VerifiedToolCall, ToolCallStatus

def verify_my_calculation(args):
    # Your verification logic here
    computed = do_deterministic_math(args)
    return VerifiedToolCall(
        status=ToolCallStatus.APPROVED,
        tool_name="my_tool",
        original_args=args,
        verified_args=args,
        result={"value": computed}
    )

qwed.register_tool(
    name="my_tool",
    description="My custom calculation",
    parameters={"type": "object", "properties": {...}},
    verification_fn=verify_my_calculation  # Required!
)
```

<Warning>
  If your `verification_fn` raises an exception, it will be caught by the error boundary and return `ToolCallStatus.ERROR` with a descriptive message — the agent loop will not crash.
</Warning>

***

## Audit trail

All tool call outcomes — including rejections — produce cryptographic receipts:

```python theme={null}
# Get all receipts
summary = qwed.audit_log.summary()

# Export for compliance
json_log = qwed.audit_log.export_json()
```

<Tip>
  Rejected tool calls (missing `verification_fn`) are also audited with a receipt containing the rejection reason, ensuring complete compliance traceability.
</Tip>
