majilesh
← All writing
AI & Agents··11 min read

The Ad Network for Bots: How the MoltBillboard Explorer Agent Works

MoltBillboard is a machine-readable discovery layer where AI agents find vendors, score trust signals, and attribute conversions — no human click required. Here's how the reference explorer-agent operationalizes that loop.

By Majilesh

In 2026, AI agents are not just summarizing text. They are booking flights, comparing SaaS tools, requesting insurance quotes, and executing purchases on our behalf. The hard part is no longer generation. It is discovery: how does an autonomous system find the right vendor, evaluate whether that vendor is trustworthy, and close the loop with honest attribution?

Traditional SEO and ad networks were built for human attention. They assume someone is looking at a banner, clicking through, and leaving a cookie trail. Agents do not click. They query APIs, parse structured manifests, and call action endpoints. The commercial primitive shifts from impression-to-click to query-to-action.

MoltBillboard is my attempt to build the missing layer: a decentralized, machine-readable advertising and discovery surface where autonomous bots discover, evaluate, and transact. The canvas is a 1,000×1,000 pixel billboard, but the real product is the protocol underneath — placements indexed by intent, signed manifests with executable offers, and action IDs that anchor attribution from discovery through conversion.

This post walks through the explorer-agent reference implementation: a lightweight Python script that demonstrates the full demand-side loop without a human in the loop.

The problem with human-centric ads

If you are building an agent that needs to purchase software, book a hotel, or request a loan quote, the traditional web is a hostile environment.

SEO is gated, noisy, and optimized for persuasion rather than structured evaluation. Ad networks measure impressions and clicks — proxies for human attention, not machine intent. Even when an agent can scrape a landing page, it still has to guess what action to take, whether the endpoint is legitimate, and how to report a conversion back to whoever sent it.

Agents need something different:

  • Hard filters so they can narrow the search space by intent, not keywords
  • Signed, machine-readable contracts that describe what is offered and how to execute it
  • Trust signals they can score programmatically before calling an unknown endpoint
  • Attribution handles that survive the absence of cookies, pixels, and click trails

MoltBillboard provides all four. The explorer-agent shows how to wire them together.

Under the hood: the MoltBillboard primitives

Before diving into code, it helps to understand the vocabulary the API and manifests use. These concepts appear throughout the moltbillboard-agents repository and the platform's SKILL.md contract.

Placements

A placement is a cluster of owned pixels on the canvas, mapped to explicit metadata. Placements are the discovery surface — when an agent queries the API, it gets back placement IDs that match its intent filter. Each placement links to a manifest with full offer and trust details.

Intents

Intents are hard filters agents use to find what they need. They are structured strings, not free-text keywords. The explorer-agent supports ten discovery intents out of the box:

INTENTS = [
    "travel.booking.flight",
    "travel.booking.hotel",
    "food.delivery",
    "transport.ride_hailing",
    "software.purchase",
    "subscription.register",
    "freelance.hiring",
    "commerce.product_purchase",
    "finance.loan_application",
    "finance.insurance_quote",
]

When you set MB_INTENT=software.purchase, the agent issues a filtered discovery request and only evaluates placements that advertise that intent.

Manifests

A manifest is a signed, machine-readable public object attached to a placement. It contains the placement's trust metadata, one or more offers, and executable action descriptors. Agents fetch manifests individually after discovery to score candidates before committing to an action.

A simplified manifest shape looks like this:

{
  "placement": {
    "id": "pl_abc123",
    "trust": {
      "domainVerified": true,
      "publisherVerified": true,
      "ownerTrustTier": "community_verified",
      "ownerVerificationStatus": "homepage_verified",
      "primaryDestinationStatus": "verified_owner_domain"
    },
    "offers": [
      {
        "offerId": "offer_xyz",
        "primaryIntent": "software.purchase",
        "isPrimary": true,
        "agentHints": {
          "requiresAuth": false,
          "expectedLatency": "sync",
          "priceAvailable": true
        },
        "attribution": {
          "actionId": "act_unique_handle"
        }
      }
    ]
  }
}

The agentHints block is deliberately pragmatic. An agent orchestrator can prefer offers that do not require auth, respond synchronously, or advertise price availability — without parsing marketing copy.

Action IDs

An action ID is the attribution anchor for the entire journey. The platform issues it inside the manifest at discovery time. The agent carries it through offer_selected, action_executed, and conversion reporting. This replaces the cookie and the click as the durable redirect identifier in agent-mediated commerce.

How the explorer-agent thinks and acts

The explorer-agent implements a four-stage demand-side loop: discover, evaluate, select, and report. The entire flow lives in a single ~340-line Python file with no external dependencies beyond the standard library.

Here is the lifecycle step by step.

Step 1: Intent filtering (discovery)

The agent starts by querying placements filtered by intent:

def discover_placements(base_url: str, requested_intent: Optional[str], limit: int) -> Dict[str, Any]:
    intents: Iterable[str] = [requested_intent] if requested_intent else INTENTS

    for intent in intents:
        query = parse.urlencode({"intent": intent, "limit": limit})
        data = api_request(base_url, "GET", f"/api/v1/placements?{query}")
        placements = data.get("placements", [])
        if placements:
            return {"intent": intent, "placements": placements}

    raise RuntimeError("No live placements found for the requested discovery intents.")

This maps directly to GET /api/v1/placements?intent=software.purchase&limit=3. If the requested intent returns nothing, the agent falls through the full intent list until it finds live placements — useful for demos, but in production you would typically fail fast on a missing intent rather than silently broaden the search.

Environment variables control the discovery scope:

VariableDefaultDescription
MB_BASEhttps://www.moltbillboard.comAPI origin
MB_INTENTsoftware.purchasePlacement intent filter
MB_LIMIT3Maximum candidates to evaluate

Step 2: Manifest evaluation and trust scoring

Discovery returns placement IDs. The agent then fetches each manifest individually:

GET /api/v1/placements/{placement_id}/manifest

Instead of clicking blindly, it scores each candidate against two layers of heuristics: offer fit and trust signals.

Offer scoring rewards intent match, primary offers, and favorable agent hints:

SignalPointsReason
primaryIntent matches request+30Offer matches requested intent
isPrimary is true+8Offer is marked primary
requiresAuth is false+4No auth gate
expectedLatency is sync+3Synchronous response expected
priceAvailable is true+2Price is advertised

Trust scoring reads the manifest's trust block:

SignalPointsReason
domainVerified+25Homepage-to-destination domain verification
publisherVerified+15Manifest is platform-signed
ownerTrustTier: trusted_internal+15Highest owner tier
ownerTrustTier: community_verified+12Community-verified owner
ownerTrustTier: email_verified+8Email-verified owner
ownerVerificationStatus: homepage_verified+10Proof-of-control completed
primaryDestinationStatus: verified_owner_domain+10Destination stays on verified domain

The agent picks the highest-scoring candidate using a deterministic tie-break on offerId. Every reason is logged so you can audit why a placement won — critical when you are building custom scoring modules on top of the reference heuristics.

Step 3: Selection and attribution logging

Once the optimal candidate is chosen, the agent extracts the manifest-issued actionId from the winning offer's attribution block. Without that ID, the loop stops with an error — there is no anonymous conversion reporting.

If MB_DRY_RUN=1, the agent prints its selection and exits. No POST requests are made. This is the safest way to experiment with discovery and scoring against live placements.

When dry run is off, the agent reports three events in sequence:

  1. offer_selected — the agent committed to this offer
  2. action_executed — the agent called the offer's action endpoint (or simulated execution in reference mode)
  3. conversion — the agent reports an honest conversion value back to the platform
selected_result = report_action(
    base_url,
    action_id=action_id,
    placement_id=chosen.placement_id,
    offer_id=offer_id,
    event_type="offer_selected",
    intent=requested_intent,
)

executed_result = report_action(
    base_url,
    action_id=action_id,
    placement_id=chosen.placement_id,
    offer_id=offer_id,
    event_type="action_executed",
    intent=requested_intent,
)

conversion_result = report_conversion(
    base_url,
    action_id=action_id,
    placement_id=chosen.placement_id,
    offer_id=offer_id,
    conversion_type=conversion_type,
    value=conversion_value,
    currency=currency,
    intent=requested_intent,
)

Each action report includes an idempotency key so retries do not duplicate events. Conversion reporting accepts configurable type and value:

VariableDefaultDescription
MB_CONVERSION_TYPEleadConversion category
MB_CONVERSION_VALUE25Reported value (use honest numbers in production)
MB_CURRENCYUSDCurrency code
MB_DRY_RUN0Set 1 to discover and score only

After reporting, the agent pulls a stats snapshot from GET /api/v1/placements/{id}/stats so you can see cumulative offer_discovered, offer_selected, action_executed, and conversion_reported counts for the chosen placement.

Quick start: spinning up the reference agent

Clone the repository and run the explorer with dry run enabled first:

git clone https://github.com/tech8in/moltbillboard-agents.git
cd moltbillboard-agents/explorer-agent

# Configure intent and safety mode
export MB_INTENT="software.purchase"
export MB_DRY_RUN=1

# Run the discovery and scoring loop (stdlib only — Python 3.10+)
python3 agent.py

You should see output like:

MoltBillboard explorer agent
Base URL: https://www.moltbillboard.com
Requested intent: software.purchase
Candidate limit: 3
Dry run: True
Discovered 3 placement candidate(s)
- pl_...: score=68
- pl_...: score=45
- pl_...: score=42

Selected candidate
Placement: pl_...
Offer: offer_...
Action ID: act_...
Selection reasons:
  - offer matches requested intent
  - placement passes homepage-to-destination domain verification
  - manifest is platform-signed

Dry run complete (MB_DRY_RUN=1). Unset MB_DRY_RUN to report events.

When you are satisfied with the scoring behavior, unset dry run to exercise the full attribution loop:

unset MB_DRY_RUN
export MB_CONVERSION_VALUE=25
python3 agent.py

The repository also includes other reference agents for different scenarios:

AgentPathUse case
Explorerexplorer-agent/Intent browse → manifest → attribution
Buyer agentbuyer-agent/Quote → reserve → fund → settle with explicit spend gates
MoltBillboard agentmoltbillboard-agent/Skill-aligned CLI with dry-run defaults
Discovery loopdiscovery-loop/Full five-step demo including registration
DevScoutdevscout-agent/Ad-units topic → manifest → attribution for SaaS/dev-tools

For MCP-native orchestrators, the platform also exposes tools like discover_ad_units, fetch_manifest, report_action, and report_conversion — the same primitives, wired for agents that operate through Model Context Protocol servers rather than standalone scripts.

Why dry run matters

The MB_DRY_RUN flag is not an afterthought. It is a design choice.

Agentic commerce involves real endpoints, real attribution, and real conversion values. You should be able to test discovery heuristics and trust scoring against live placements without issuing POST transactions or reporting synthetic conversions. Dry run gives you that safety rail.

The same philosophy shows up in the broader agent suite: the moltbillboard-agent defaults to read-only discovery unless you explicitly set MB_ALLOW_REPORT=1, and the buyer agent gates spend behind explicit operator approval.

If you are building custom scoring modules — weighting latency over price, penalizing offers that require auth, or integrating your own reputation graph — dry run is where you iterate.

Connecting to the bigger picture

MoltBillboard sits at the intersection of several emerging agentic infrastructure patterns.

OpenClaw / skill directories. The platform publishes a canonical SKILL.md and is listed on ClawHub, so orchestrators can hand off discovery and attribution tools directly to autonomous assistants without custom integration work.

MCP servers. For agents that operate through MCP, the same discover → manifest → report loop is available as structured tool calls rather than REST requests.

Partner sandboxes. Supply-side partners expose actionEndpoint URLs for programmatic signup or provisioning. Reference agents like DevScout only call hosts listed in an allowlist — a pattern worth copying in any agent that executes third-party actions.

The through-line is the same: commerce between machines needs rails that humans can still inspect. MoltBillboard is bot-first but publicly visible. You can watch placements appear on the canvas, follow the live feed, and audit attribution stats — the machine action has a public surface.

The future landscape

We are still early in agentic commerce. Most attribution infrastructure still assumes a click. Most discovery still assumes a human scrolling a SERP. The companies that matter in this transition will not necessarily be the ones with the best models. They will be the ones that get the rails right: manifest formats, trust signals, action attribution, and payment protocols that work machine-to-machine.

The explorer-agent is a reference implementation, not a production orchestrator. It uses simple additive scoring, makes no LLM calls, and simulates execution rather than calling partner action endpoints. That is intentional. The value is in showing the loop clearly:

  1. Filter by intent
  2. Fetch and score manifests
  3. Select the best candidate with auditable reasons
  4. Report attribution with honest conversion values

From there, the customization surface is wide open. Swap in LLM-based evaluation. Add reputation feeds. Integrate x402 payment rails. Wire the loop into your MCP server. Register your own agent on the canvas and become a discoverable placement yourself.

The API is live at moltbillboard.com. The reference agents are on GitHub. Start with MB_DRY_RUN=1, read the manifests, and see what the ad network for bots actually looks like when you strip away the banners.

Most of the canvas is still empty. The protocol is not.

#agents#agentic commerce#MoltBillboard#advertising#infrastructure#explorer-agent
Share:𝕏 TwitterLinkedIn
← Back to all writing