Agent frameworks / LangChain

LangChain

Give a LangChain or LangGraph agent the AIX tools through the MCP server, or define the two tools in code, with the timing rules the model needs.

LangChain agents take a list of tools. An AIX integration adds two: submit_intent after any turn that states or changes what the shopper wants to buy, and report_handoff before the shopper is sent to a store. Both run on your server with your key.

Through the MCP server

LangChain 1.4 and later ship an MCP adapter in the langchain.mcp namespace (beta). It delegates the connection to FastMCP's client, so the key is passed as the client's auth, which becomes the Authorization: Bearer header. The MCP submit_intent tool takes one argument, intent, with the same body as POST /intents (its turn input is reserved for Brambles-managed publishers; the model must send exactly one of the two).

bash
pip install "langchain[mcp]>=1.4.0"
python
import os
from fastmcp.client import Client
from langchain.agents import create_agent
from langchain.mcp import MCPAdapter
AIX_MCP = "https://aix.brambles.ai/api/aix/mcp"
async def run(user_message: str) -> str:
async with MCPAdapter(Client(AIX_MCP, auth=os.environ["AIX_PUBLISHER_KEY"])) as adapter:
tools = await adapter.list_tools()
agent = create_agent(model, tools, system_prompt=AIX_RULES) # see below
result = await agent.ainvoke({"messages": [("user", user_message)]})
return result["messages"][-1].content

Before 1.4, the langchain-mcp-adapters package does the same with a headers field:

python
from langchain_mcp_adapters.client import MultiServerMCPClient
client = MultiServerMCPClient({
"aix": {
"transport": "streamable_http",
"url": "https://aix.brambles.ai/api/aix/mcp",
"headers": {"Authorization": f"Bearer {os.environ['AIX_PUBLISHER_KEY']}"},
}
})
tools = await client.get_tools()

Defined in code

Two tools and one request helper with a three-second timeout. Every failure returns a skipped result so AIX can never slow down or break the shopper's experience. submit_intent takes the same intent argument as the MCP tool, so one prompt works whichever way the tools arrive.

python
import os
from typing import Literal
import httpx
from langchain_core.tools import tool
from pydantic import BaseModel, Field
AIX = "https://aix.brambles.ai/api/aix"
class Budget(BaseModel):
currency: str = Field(min_length=3, max_length=3)
max_cents: int
class Fact(BaseModel):
attribute: Literal["brand", "width", "size", "department", "use_case", "feature", "merchant", "deal"]
value: str
strength: Literal["required", "preferred", "excluded"]
class Task(BaseModel):
category: str
summary: str = Field(max_length=1600)
budget: Budget | None = None
facts: list[Fact] = []
class Intent(BaseModel):
session_id: str = Field(min_length=1, max_length=128)
country: str = Field(min_length=2, max_length=2)
task: Task
async def _aix(path: str, body: dict) -> dict:
key = os.environ.get("AIX_PUBLISHER_KEY")
if not key:
return {"status": "skipped", "reason": "no_key"}
try:
async with httpx.AsyncClient(timeout=3) as client:
r = await client.post(f"{AIX}/{path}", json=body, headers={"Authorization": f"Bearer {key}"})
return r.json() if r.is_success else {"status": "skipped", "reason": f"http_{r.status_code}"}
except httpx.HTTPError:
return {"status": "skipped", "reason": "timeout"} # never block the shopper
@tool
async def submit_intent(intent: Intent) -> dict:
"""Report the shopper's current shopping task to AIX. Call after any turn that states or changes
what they want to buy, with intent: session_id, country and the task. Shopping requirements only,
never personal data."""
return await _aix("intents", intent.model_dump(exclude_none=True))
@tool
async def report_handoff(session_id: str, destination_url: str, consent: str | None = None) -> dict:
"""Report that the shopper is being sent to a store or product page (the store's own URL).
Use the returned landing_url as that page's URL, inside your affiliate link if you use one."""
body: dict = {"session_id": session_id, "destination_url": destination_url}
if consent:
body["consent"] = consent
return await _aix("handoffs", body)
agent = create_agent(model, [submit_intent, report_handoff], system_prompt=AIX_RULES)

The rules the model needs

Put this in the system prompt:

text
You can send shopping intent to the Agentic Intent Exchange (AIX).
- After any user turn that states or changes what they want to buy, call submit_intent with one
argument, intent: an object holding the conversation's session_id, the shopper's two-letter
country, and the task: a category, a one-line summary, the budget when they gave one, and facts
with attribute, value and strength (required, preferred or excluded). Send only shopping
requirements: never names, emails, phone numbers, addresses, account or order numbers, or the
conversation itself.
- Before you give the user a link to a store or product page, call report_handoff with the same
session_id and the store's page URL, then use the returned landing_url as that page's URL (inside
your own affiliate or ad link, if you use one).
- If either tool fails or is slow, carry on without it. Never ask the user for a key.

Set country on the server from your host's geolocation header rather than asking the shopper. Shoppers in the EEA, the UK or Switzerland are shared only with consent: show one line under your assistant, "Clicking a store link shares your shopping request with that store", and pass consent: "granted" on handoffs from those clicks. Sensitive topics are suppressed by AIX on arrival; never reword a task to get it through.

Receiving side

A store's agent uses the same connection with AIX_RECEIVER_KEY; the tools then list deliveries (subscribe_intents), read one receipt (get_intent_context), acknowledge it (acknowledge_delivery) and redeem a handoff id from a landing or a checkout (redeem_handoff; with a sandbox key it returns a free test delivery for any well-formed id). Verification and acknowledgment belong on your server; see Receiving agents.

Test it

  1. Create a free sending agent in the AIX console and store the sandbox key as AIX_PUBLISHER_KEY.
  2. Run one conversation that names a product and ends with a store link. The intent answers accepted; the handoff answers test_delivered with a receiver_preview.
  3. GET /activity with the same key, or the AIX console, shows the test. Create the production key there and set it in production.
Was this helpful?