Docs
Plugins, Decisioners, and MCP tools
Add bidding, pricing, targeting, and other serving behavior with an ExtensionService plugin. Use a Decisioner for model-based decisions, or the Admin API and MCP for applications and agents. The examples below include local tests and installation instructions.
Download working starters
Download source, tests, setup instructions, and a coding-agent prompt for each example. You can run them locally without a private Riptide checkout. To connect an example to serving, deploy the service and register it with an authorized tenant. See all examples and workflow prompts for API, reporting, serving and webhook integrations.
Decisioner (HTTP)
Test a floor-pricing rule locally, then compare it with the baseline in shadow mode. This Go HTTP service returns a decimal floor decision; the guide covers registration as an EXTERNAL_ENDPOINT model.
Extension sidecar
Start a custom bidding, targeting, pricing or rendering integration from a working gRPC service. The archive includes small policies for all eight plugin kinds, plus local tests for Describe, Health and Invoke.
Build with your coding agent
Each archive contains a focused PROMPT.md. For one prompt that covers plugins, Decisioners and MCP tools, see the agent prompt for extensions.
Choose a plugin kind
Each sidecar process runs one plugin kind and implements riptide.ext.v1.ExtensionService with
Describe, Health and Invoke. The archive's README maps
each kind to its command, JSON payload, expected output and conformance test.
| Kind / wire method | Serving configuration | On failure |
|---|---|---|
BID_SOURCEGetBids | Adds bid candidates for the tenant. The auction applies its usual eligibility and pricing rules. | No additional bids. |
DEMAND_ADAPTERBuildRequests / ParseResponse | Demand partner adapter must be sidecar; routes provide the buying configuration. The host performs outbound requests. | No requests or bids from that integration. |
ENRICHEREnrich | Runs during enrichment when privacy permits; fills unresolved signals and adds segments. | Request remains unchanged. |
AUDIENCE_EVALUATOREvaluate | Audience custom_rules.evaluator names the configured dimension or *; matched segments feed targeting. Privacy gates still apply. | No matching segments; evaluator returns pass=false. |
PRICING_MODULEApplyPricing | Runs after pricing. Net price must stay between zero and gross price, and gross price cannot increase. | Keep the original prices. |
CREATIVE_RENDERERRender | Select media in the install configuration. Supports platform-rendered display/native markup on OpenRTB and Decision API requests. VAST rendering is unsupported. | Keep the platform-rendered markup. |
VERIFICATION_VENDORPreBid | Configure verification_slot and pre_bid for pre-bid signals and pixel suppression, subject to privacy policy. External measurement SDKs require a separate integration. | No extra verification signals; configured platform policies still apply. |
DEMAND_ATTACHMENTPick | Select eligible non-rendered demand candidates for a carrier under the attachment policy. The baseline is used when no sidecar is installed. | No extra attachments; the carrier remains. An installed sidecar failure does not retry the baseline. |
Declare name, version, kind, entitlement, health behavior, a latency budget and a config
schema. Serve-path budgets must be positive and at most 50 ms; aggregate extension budgets
also need to fit the auction deadline. Honor cancellation and avoid network work beyond
that budget. Declare only the request keys you need in
config_schema.context_fields; receive per-tenant configuration through
tenant_config. Money remains decimal strings, such as "2.5000".
The bundled policies use a local -config file and do not inspect
tenant_config. Run separate instances for tenants with different policies, or
implement and test tenant-config handling when adapting the starter. An installation's
config_json selects host behavior such as renderer media; it does not
automatically override the starter's process policy.
Build report clients against the reporting catalog, and register Decisioners through the
model workflow below. The retired REPORT_FIELD and DECISIONER
ExtensionService kinds are rejected on new listings. Adding a stored report dimension
requires a schema and catalog change in a customer checkout.
Publish and install a sidecar
Start with go test ./... and the smoke command in the extracted archive. Deploy
the selected service where your Riptide cell can reach it, then arrange the endpoint reference
and required secrets with the platform operator. Local tests do not install the service in
a managed cell. Keep credentials in your secret store and out of listing metadata and source.
| Admin operation | What it does |
|---|---|
createMarketplaceListing | Create a DRAFT STACK_PRODUCT listing with public metadata and pricing. |
runExtensionConformance | Operator records the result of independently executed and reviewed conformance tests. |
publishStackProduct | Publish after vendor entitlement, configuration, budgets and verified PASS checks. |
installStackProduct | Install a published listing with listing_id and a JSON-encoded config_json string. |
listTenantExtensions | Read installed kinds and budgets; endpoint secrets are not returned. |
uninstallStackProduct | Revoke the activation and remove its serving projection on the next plan refresh. |
Listing metadata uses kind: STACK_PRODUCT, distribution: SIDECAR_ENDPOINT,
extension_kinds, endpoint_ref, config_schema (JSON as a
string), latency_budget_ms, conformance_run_id, trust requirements
and decimal pricing. Publish requires vendor entitlement and a PASS with
operator_verified=true. The runExtensionConformance endpoint
does not execute the harness: an operator must run and review the tests
before recording that evidence. Customer checkouts include the host harness at
plugins/sidecar/conformance.
After publication, use installStackProduct:
POST /v1/tenants/{tenant_id}/stack-products/install with your API key and
a stable Idempotency-Key. Replace the listing ID and match the config to its
schema. For a display renderer, the host selection includes media: banner:
{
"listing_id": "018f0000-0000-7000-8000-000000000020",
"config_json": "{\"media\":\"banner\"}"
}
Save the activation ID so you can uninstall later. Check the installation with
listTenantExtensions, then wait for the next serving plan and send a test
request that uses this plugin kind. Inspect request diagnostics and extension telemetry
to confirm it ran. An
uninstallStackProduct call revokes that activation; existing requests finish
against their captured plan.
Decisioners: register a model and start in shadow
A Decisioner preserves a deterministic baseline and evaluates an optional candidate.
BASELINE uses platform behavior, SIDECAR uses the separate gRPC
DecisionService, and EXTERNAL_ENDPOINT accepts protojson
DecideRequest over HTTP. The HTTP example implements a floor policy.
Measure its effect on your traffic in shadow mode before considering promotion.
Deploy the HTTP starter behind public HTTPS with a valid certificate. The serving host
rejects plain HTTP, loopback and private-network HTTP destinations. Replace the example
hostname below, then call createModel at
POST /v1/tenants/{tenant_id}/models with an idempotency key:
{
"decision_point": "floor",
"name": "my-floor-policy",
"version": "1.0.0",
"kind": "EXTERNAL_ENDPOINT",
"config": {
"url": "https://decisioner.example.com/decide"
}
}
Use the returned model ID with assignModel at
POST /v1/tenants/{tenant_id}/models/{model_id}/assignments:
{"decision_point":"floor","mode":"SHADOW","traffic_pct":"100.0000"}
SHADOW measures the candidate while baseline decisions serve. Review decision records and
record an evaluation using recordEvaluationRun. Promotion through
promoteModel (MCP riptide.model.promote_decisioner) requires the
platform operator and measured evidence before bounded A/B or live use. Failure or timeout
falls back to the baseline. Tenant creation/assignment/evaluation requires
model.write; it does not grant model.promote.
Build applications with API and MCP
A reporting tool, campaign assistant or administration integration should call existing
Admin API operations or MCP tools. New core
operations require a customer checkout and contract regeneration. The
examples page includes code and prompts for these workflows.
You can also use the CLI's riptide ext init command to clone an example repository.
Start with a working example
Download a serving plugin or floor Decisioner, run its local tests, then adapt the policy to your integration. The capability guides explain what each example produces and how to connect it.