# Python SDK Reference

Source: https://docs.aon.pro/sdk/python

> Derived from the same AON Docs release as the source page.

Signature-first reference for `agentoffernetwork`.

> Protocol default
>
> The live client sends the exact current selector `AON-Protocol-Version: 1.0`. Returned Offers follow the canonical Protocol v1.0 schema and generated SDK types.

> Package
>
> Install with `pip install agentoffernetwork` or `uv add agentoffernetwork`. Current documented version: v1.0.0

> Pinned docs baseline
>
> This reference targets the current repository baseline: Python 3.11+ and `agentoffernetwork` `v1.0.0`.

Use live mode only with an issued Live Key owned by a serviceable Application. Installation, package imports, and a local mock do not establish this access condition.

## Primary Exports

```python
from agentoffernetwork import (
    initialize,
    create_context_for_platform,
    detect_context,
    format_recommendation,
    AON_CURRENT_PROTOCOL_VERSION,
    AON_PROTOCOL_VERSION_V10,
    AgentOfferClient,
    MockAgentOfferClient,
    SDKConfig,
    QueryOffersParams,
    QueryContext,
    QuerySession,
    QueryPlatform,
    Intent,
    TextContentPart,
    QueryConstraints,
    QueryOffersResponse,
    ClickEvent,
    ConversionEvent,
    FormatOptions,
)
```

## initialize(config)

Creates a live or mock client after validating configuration.

initialize(config)

Python

```
client = await initialize(SDKConfig(
    api_key="your-token",
    mode="live",
    base_url="https://api.aon.pro",
    timeout=5000,
))
```

Parameter

Description

`api_key`

strRequired

Bearer token used for live API requests. Must be non-empty.

`mode`

Literal\["mock", "live"\]Required

mock returns local sample data; live uses the HTTP API.

`base_url`

strOptional

Overrides the default live API origin. Defaults to https://api.aon.pro.

`timeout`

float | NoneOptional

Timeout value accepted by the SDK config. Current live implementation interprets 5000 as a five second timeout.

Validation behavior:

-   Empty `api_key` raises `AonValidationError`.
-   Any mode other than `mock` or `live` raises `AonValidationError`.
-   `timeout <= 0` raises `AonValidationError`.

## AgentOfferClient Protocol

```python
class AgentOfferClient(Protocol):
    async def query_offers(self, params: QueryOffersParams) -> QueryOffersResponse: ...
    async def report_click(self, event: ClickEvent) -> ClickResult: ...
    def format_recommendation(self, offer: Offer, options: FormatOptions | None = None) -> str: ...
```

All network-calling methods are async. `format_recommendation` is synchronous.

## query\_offers(params)

`query_offers` serializes dataclass fields to protocol snake\_case and sends `POST /v1/offers/query` in live mode.

```python
response = await client.query_offers(QueryOffersParams(
    request_id="req-123",
    context=QueryContext(
        platform=QueryPlatform(name="shopping-bot", channel="api"),
        session=QuerySession(recent_topics=["audio"]),
    ),
    intent=Intent(content=[
        TextContentPart(type="input_text", text="noise cancelling headphones under $200"),
    ], provenance="user_expressed", signals={"budget": {"max": 200, "currency": "USD"}}),
    constraints=QueryConstraints(
        category_ids=["computers_electronics.consumer_electronics"],
    ),
    force_offer=True,
    response_options={"thinking_mode": True},
))
```

Parameter

Description

`request_id`

str | NoneOptional

Optional caller-supplied request identifier.

`timestamp`

str | NoneOptional

Optional RFC 3339 timestamp.

`test_mode`

bool | NoneOptional

Marks the request as test traffic.

`context`

QueryContextRequired

Bounded platform, session, session\_id, and conversation\_id context. Long-term profiles are not sent on the Protocol v1.0 wire.

`intent.content`

list\[ContentPart\]Required

At least one content part. Supported variants are input\_text and input\_image.

`intent.provenance`

user\_expressed | inferred\_contextOptional

Defaults to user\_expressed. Inferred intent requires a bounded confidence value.

`constraints`

QueryConstraints | NoneOptional

category\_ids and excluded\_category\_ids.

`force_offer`

bool | NoneOptional

Permits a qualified fallback Offer when an exact match is unavailable.

`response_options.thinking_mode`

bool | NoneOptional

Defaults to true. Set false to omit offer match\_reason values.

`QueryOffersResponse` shape:

```python
QueryOffersResponse(
    request_id=str,
    offers=list[Offer],
    query_id=str | None,  # deprecated legacy alias for request_id
    total=int | None,     # SDK-derived convenience, not a protocol response field
    has_more=bool | None, # SDK-derived convenience, not a protocol response field
)
```

Important notes:

-   `validate_content()` runs before the HTTP request.
-   `request_id` maps to protocol `data.request_id`. `query_id` is a deprecated legacy alias when present.
-   The SDK selects Protocol `1.0` and validates returned Offers against the current contract.
-   `total` and `has_more` are SDK-derived conveniences, not protocol/OpenAPI response fields.
-   The SDK exposes protocol `offer_id` as `offer.offer_id` and `offer_instance_id` as `offer.offer_instance_id`.
-   `tracking_url` is the AON tracking endpoint supplied by your integration layer for the selected offer.

## report\_click(event)

`report_click` performs a `GET` against the offer's tracking URL and extracts the tracking identifier from that URL.

```python
click = await client.report_click(ClickEvent(
    offer_id=offer.offer_id,
    tracking_url="https://tracking.example.test/click/mock-track-1",
    timestamp="2026-04-16T12:00:00Z",
    agent_id="shopping-bot",
    session_id="session-123",
    context={"conversation_id": "conv-456"},
))
 
print(click.tracking_id)
print(click.timestamp)
```

Parameter

Description

`offer_id`

strRequired

Offer identifier from query results.

`tracking_url`

strRequired

AON tracking URL supplied by your integration layer for the selected offer. Do not synthesize it from offer\_id.

`timestamp`

strRequired

Client-side event timestamp.

`agent_id`

str | NoneOptional

Optional identifier for the calling agent.

`session_id`

str | NoneOptional

Optional session key for deduplication and analytics.

`context`

dict\[str, Any\] | NoneOptional

Optional structured metadata.

## format\_recommendation(offer, options=None)

Formats an `Offer` into display-ready text. The standalone function and the client method share the same implementation.

```python
text = client.format_recommendation(offer, FormatOptions(
    style="markdown",
    include_disclosure=True,
    disclosure_text="Sponsored",
    include_price=True,
))
```

Parameter

Description

`style`

Literal\["brief", "detailed", "markdown"\]Optional

Output style. Defaults to markdown.

`include_disclosure`

boolOptional

Whether to append the disclosure label. Defaults to true.

`disclosure_text`

strOptional

Disclosure label text. Defaults to Sponsored.

`include_price`

boolOptional

Whether to include price if the offer contains one. Defaults to true.

## detect\_context(...)

`detect_context()` builds a `QueryContext` with platform, language, and session defaults.

```python
context = detect_context(
    platform_name="custom-agent",
    channel="api",
    user_pseudo_id="anon-42",
    interests=["travel", "credit cards"],
)
```

Auto-detection behavior:

-   Non-TTY processes default to `mcp-skill` / `mcp`.
-   Other runtimes default to `sdk` / `api`.
-   `LANG`, `LC_ALL`, or `LC_MESSAGES` drive language detection.
-   A session identifier is generated once per process.

## create\_context\_for\_platform(target, ...)

Use the explicit platform adapter when the host platform is already known.

```python
from agentoffernetwork import create_context_for_platform, CustomPlatformTarget
 
mcp_context = create_context_for_platform(
  "mcp-skill",
  interests=["Apple ecosystem user"],
)
 
coze_context = create_context_for_platform(
  "coze",
  native_user_id="user-123",
  native_session_id="conv-1",
)
 
custom_context = create_context_for_platform(
  CustomPlatformTarget(name="partner-builder", channel="agent"),
)
```

Built-in targets:

-   `sdk` → `platform.name = sdk`, `platform.channel = api`
-   `mcp-skill` → `platform.name = mcp-skill`, `platform.channel = mcp`
-   `chatgpt` → `platform.name = chatgpt`, `platform.channel = action`
-   `coze` → `platform.name = coze`, `platform.channel = plugin`, native user IDs normalize to `coze:<id>`
-   `dify` → `platform.name = dify`, `platform.channel = tool`, native user IDs normalize to `dify:<id>`

Notes:

-   Explicit `platform_name`, `channel`, `session_id`, and `user_pseudo_id` overrides always win.
-   Empty native user IDs do not produce guessed `user_pseudo_id` values.
-   ChatGPT Action integrations should still omit `platform` and `user_pseudo_id` in the request body; the F011 server path injects them automatically.

## Mock Testing

Mock mode records click and conversion events in memory.

```python
mock = await initialize(SDKConfig(api_key="test-key", mode="mock"))
 
await mock.report_click(ClickEvent(
    offer_id="offer-1",
    tracking_url="https://example.com/track/mock-track-1",
    timestamp="2026-04-16T12:00:00Z",
))
 
print(mock.get_recorded_events())
```

## Error Classes

| Class | Code | When it is raised |
| --- | --- | --- |
| `AonValidationError` | `VALIDATION_ERROR` | Invalid SDK configuration or invalid query content |
| `AonAuthError` | `AUTH_ERROR` | 401 responses or failed authentication |
| `AonRateLimitError` | `RATE_LIMIT` | 429 responses |
| `AonNetworkError` | `NETWORK_ERROR` | Timeout, transport, or non-JSON transport failures |
| `AonApiError` | server-provided | API returned a business error code instead of `SUCCESS` |

## Python live completion

The Python path is complete only when `query_offers` with your issued Live Key returns a canonical v1.0 result. Empty offers or `data.empty_reason` are valid results. A local mock, authentication failure, or protocol failure is not live completion.

## Related TypeScript reference

-   [TypeScript SDK Reference](https://docs.aon.pro/sdk/typescript)

## Related Pages

-   [SDK Overview](https://docs.aon.pro/sdk)
-   [Python SDK Guide](https://docs.aon.pro/guides/sdk-python)

[Review Production Access & API Keys](https://docs.aon.pro/quickstart/get-api-key)

[Review Authentication](https://docs.aon.pro/api/authentication)
