Python SDK Reference
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
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.
client = await initialize(SDKConfig(
api_key="your-token",
mode="live",
base_url="https://api.aon.pro",
timeout=5000,
))api_keyBearer token used for live API requests. Must be non-empty.
modemock returns local sample data; live uses the HTTP API.
base_urlOverrides the default live API origin. Defaults to https://api.aon.pro.
timeoutTimeout value accepted by the SDK config. Current live implementation interprets 5000 as a five second timeout.
Validation behavior:
- Empty
api_keyraisesAonValidationError. - Any mode other than
mockorliveraisesAonValidationError. timeout <= 0raisesAonValidationError.
AgentOfferClient Protocol
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.
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},
))request_idOptional caller-supplied request identifier.
timestampOptional RFC 3339 timestamp.
test_modeMarks the request as test traffic.
contextBounded platform, session, session_id, and conversation_id context. Long-term profiles are not sent on the Protocol v1.0 wire.
intent.contentAt least one content part. Supported variants are input_text and input_image.
intent.provenanceDefaults to user_expressed. Inferred intent requires a bounded confidence value.
constraintscategory_ids and excluded_category_ids.
force_offerPermits a qualified fallback Offer when an exact match is unavailable.
response_options.thinking_modeDefaults to true. Set false to omit offer match_reason values.
QueryOffersResponse shape:
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_idmaps to protocoldata.request_id.query_idis a deprecated legacy alias when present.- The SDK selects Protocol
1.0and validates returned Offers against the current contract. totalandhas_moreare SDK-derived conveniences, not protocol/OpenAPI response fields.- The SDK exposes protocol
offer_idasoffer.offer_idandoffer_instance_idasoffer.offer_instance_id. tracking_urlis 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.
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)offer_idOffer identifier from query results.
tracking_urlAON tracking URL supplied by your integration layer for the selected offer. Do not synthesize it from offer_id.
timestampClient-side event timestamp.
agent_idOptional identifier for the calling agent.
session_idOptional session key for deduplication and analytics.
contextOptional 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.
text = client.format_recommendation(offer, FormatOptions(
style="markdown",
include_disclosure=True,
disclosure_text="Sponsored",
include_price=True,
))styleOutput style. Defaults to markdown.
include_disclosureWhether to append the disclosure label. Defaults to true.
disclosure_textDisclosure label text. Defaults to Sponsored.
include_priceWhether to include price if the offer contains one. Defaults to true.
detect_context(...)
detect_context() builds a QueryContext with platform, language, and session
defaults.
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, orLC_MESSAGESdrive 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.
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 = apimcp-skill→platform.name = mcp-skill,platform.channel = mcpchatgpt→platform.name = chatgpt,platform.channel = actioncoze→platform.name = coze,platform.channel = plugin, native user IDs normalize tocoze:<id>dify→platform.name = dify,platform.channel = tool, native user IDs normalize todify:<id>
Notes:
- Explicit
platform_name,channel,session_id, anduser_pseudo_idoverrides always win. - Empty native user IDs do not produce guessed
user_pseudo_idvalues. - ChatGPT Action integrations should still omit
platformanduser_pseudo_idin the request body; the F011 server path injects them automatically.
Mock Testing
Mock mode records click and conversion events in memory.
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.