The AIP Server is the neutral, protocol-only runtime for the Agentic Intent Protocol (AIP). It exposes the canonical HTTP, transport, validation, and ledger execution paths used by platforms, brand agents, and neutral operators. All behavior mirrors the normative specification in the companion aip-spec repository.
aip-specdefines canonical schemas, conformance tests, and transport rules.- This repo turns that specification into a runnable FastAPI service.
- Every spec change should be reflected here via schema syncs and runtime updates.
git clone https://github.com/GouniManikumar12/aip-server-python.git
cd aip-server- Python 3.11 (works on 3.10+, tested on 3.11)
- pip 23+
- Optional: Docker + Docker Compose for container workflows
python3.11 -m venv .venv
source .venv/bin/activate
pip install --upgrade pip
pip install -r requirements.txt| Variable | Purpose |
|---|---|
AIP_CONFIG_PATH |
Override path to server.yaml (defaults to app/config/server.yaml). |
AIP_BIDDERS_PATH |
Override path to bidders.yaml. |
GOOGLE_APPLICATION_CREDENTIALS |
Service-account JSON for Google Pub/Sub or Firestore. |
Optional secrets (Postgres DSNs, Redis URLs, etc.) can live inside server.yaml under ledger.options or be injected as environment variables referenced from the YAML.
bidders:
- name: sample-bidder
endpoint: https://example-bidder.invalid/bid
public_key: "-----BEGIN PUBLIC KEY-----..."
timeout_ms: 120
pools:
- default
- retailpoolsenumerate the category pools the brand agent subscribes to.public_keyis the PEM-encoded Ed25519 key used to verify/aip/bid-responsesignatures.
listen:
host: 0.0.0.0
port: 8080
transport:
nonce_ttl_seconds: 60
max_clock_skew_ms: 500
ledger:
backend: postgres # or redis, firestore, in_memory
options:
dsn: postgresql://user:pass@localhost:5432/aip
auction:
window_ms: 50
distribution:
backend: pubsub
pubsub:
project_id: your-gcp-project
topic_prefix: aip-contextEnvironment-specific guidance:
- Development: use
backend: in_memory,distribution.backend: local, and sample bidders. - Staging/Production: point
ledger.optionsto managed stores (Postgres/Firestore/Redis), lock downlisten.host, use HTTPS termination, and rotate credentials regularly.
- Python: 3.10+
- FastAPI: async HTTP framework for
/context,/aip/bid-response,/events/{type}, and admin routes - Storage backends: In-Memory (dev/test), Redis, PostgreSQL, Google Cloud Firestore
- Transport & security primitives:
- Publish/Subscribe fanout (
app/auction/fanout.py) with local logging or Google Pub/Sub (pluggable for AWS SNS/SQS, Azure Event Grid, Kafka) - Ed25519 signatures (
app/transport/signatures.py) - Canonical JSON serialization (
app/transport/canonical_json.py) - Timestamp skew enforcement (
app/transport/timestamps.py) - Nonce replay protection (
app/transport/nonces.py)
- Publish/Subscribe fanout (
- Create a Firestore database in the desired GCP project.
- Download a service-account JSON with Firestore + Pub/Sub (if needed) permissions.
- Set
GOOGLE_APPLICATION_CREDENTIALS=/path/to/key.json. - Configure:
ledger: backend: firestore options: project_id: your-gcp-project credentials_path: /path/to/key.json # optional when env var is set
- Provision a database/user with privileges to create tables.
- Set
ledger.backend: postgresand provide either a DSN or discrete connection options underledger.options. - The backend auto-creates
ledger_recordswith a JSONB payload. Run migrations beforehand if you need indexes/partitions.
- Deploy Redis (standalone, cluster, or managed service).
- Configure
ledger.backend: rediswithoptions.url: redis://host:port/0. Userediss://for TLS endpoints. - Recommended for low-latency ledgers, nonce caches, and anti-replay enforcement.
- Set
ledger.backend: in_memoryfor local development or CI. - Data is ephemeral; never use this backend in production.
- Install dependencies (see Installation & Setup).
- Configure bidders/server (
app/config/*.yaml). - Run the API:
uvicorn app.main:app --reload --port 8080
- Docker / Compose:
docker-compose up --build # or docker build -t aip-server . docker run -p 8080:8080 aip-server
- Sanity checks:
python -m compileall app # quick syntax check # Add pytest / mypy commands as suites are introduced
- Verify endpoints:
# Health curl http://localhost:8080/health # Submit a platform request (expect no_bid when no bidders respond) curl -X POST http://localhost:8080/aip/context \ -H "Content-Type: application/json" \ -d '{ "request_id": "ctx_123", "session_id": "sess_001", "platform_id": "openai_chat", "query_text": "best CRM for small teams", "locale": "en-US", "geo": "US", "timestamp": "2025-11-14T18:22:00Z", "auth": {"nonce": "nonce_123", "sig": "sig_hmac"} }' # (During the auction window) send a mock bid response curl -X POST http://localhost:8080/aip/bid-response \ -H "Content-Type: application/json" \ -d '{ "auction_id": "ctx_123", "bidder": "sample-bidder", "price": 1.23, "timestamp": "2025-01-01T00:00:00Z", "nonce": "abc123", "signature": "..." }'
- Operators list bidder endpoints in
app/config/bidders.yamlwith public signing keys, timeouts, and category pools. - Each bidder listens to the publish/subscribe channels for its pools.
- During auctions, bidders POST signed payloads to
/aip/bid-responsebefore the configured window closes.
The AIP bidding model uses a time-bounded asynchronous auction window rather than full broadcast fanout. When a platform sends a context_request, the AIP Server classifies the request into one or more category pools.
Only brand agents and advertiser networks that have explicitly subscribed to those pools receive the request.
Distribution to bidders is handled through a cloud-agnostic publish/subscribe transport, starting with Google Pub/Sub in v1.0 and extendable to AWS SNS/SQS, Azure Event Grid, Kafka, or other message buses.
After publishing the context, the AIP Server opens a short auction window (typically 30–70 ms) during which bidders may submit signed bids via POST /aip/bid-response.
When the window closes, the server collects all bids received within the allowed timeframe, applies the AIP selection rules (CPA > CPC > CPX), and returns the auction_result to the platform.
If no bids are received before the window expires, the server returns a valid no_bid response. This design enables scalable, category-aware bidding, minimizes latency, prevents unnecessary bidder fanout, and ensures that only relevant brand agents compete for each user intent.
POST /context→app/main.py– Platforms submit context; FastAPI validates againstaip-specschemas and forwards to the auction runner.- Classification & publish →
app/auction/runner.py+app/auction/fanout.py– The runner selects subscribed bidders fromapp/bidders/registry.py, registers the auction withBidResponseInbox, and publishes{auction_id, pools, context_request}via the configured transport. - Bidder responses →
POST /aip/bid-response– Brand agents send Ed25519-signed payloads.BidResponseService(inapp/events/handler.py) enforces nonce freshness, timestamp skew, and signature validity before queuing bids. - Window close & selection →
app/auction/runner.py/app/auction/selection.py– Afterauction.window_ms, the runner drains collected bids, applies CPA>CPC>CPX ordering, and persists results viaapp/ledger/apply.py. - Response to platform –
/contextreturns the canonicalauction_result(winner + creative +serve_token) or{..., "no_bid": true}when no bids arrive in time. - Event callbacks →
POST /events/{event_type}– Platforms/agents log CPX/CPC/CPA events.EventServicevalidates payloads and advances the ledger state machine.
- Full coverage of
aip-spec/testsconformance suite in CI. - Configurable storage engines (in-memory, Redis, Postgres, Firestore) with parity semantics.
- Ledger FSM hardening plus deterministic replay protections.
- Transport hardening (nonce rotation policies, signature caching, canonical JSON round-trips).
- Reference load/seed scripts kept in sync with spec fixtures.