Skip to main content

An agentic harness for marketing measurement: adstock, saturation, attribution, and budget allocation as typed agent tools with an eval suite.

Project description

MixPilot

An agentic harness for marketing measurement.

Everyone is building general-purpose agents. MixPilot is the opposite bet: a small, real agent runtime whose entire action space is the marketing-science toolkit — adstock, saturation, multi-touch attribution, budget optimisation, and a marketing-aware data-quality audit — wired as typed tools with structured results, an approval gate, and an eval suite that scores the agent's method-selection judgment.

The thesis: in a domain agent, the tools are the product. A model can sound confident about marketing data; the hard part is knowing which method the data can actually support — and refusing the ones it can't. That judgment is what MixPilot encodes and tests.

pip install mixpilot            # tools only
pip install "mixpilot[groq]"    # + the agent loop on Groq (open models)
pip install "mixpilot[agent]"   # + the agent loop on Anthropic

The agent loop is provider-agnostic — the LLM client is injected, so the same loop runs on Groq Llama or Claude by swapping one line.

What's inside

Component What it does The lesson
audit_data_quality nulls, negative spend, zero-variance, multicollinearity The audit decides whether any later number is trustworthy at all
adstock_transform geometric carryover with half-life Carryover before saturation, always
fit_saturation_curve Hill curve (β, α, γ) + R² A low-R² curve is a warning, not a result
run_attribution_model last-touch / linear / Markov removal-effect Match the model to the data shape, never overreach
allocate_budget constrained optimisation over saturation curves Move money toward unsaturated marginal return
ToolResult contract summary + next_actions + recovery_hint on every call A tool result is the next observation, not a log line
Approval gate mutating actions clear a policy gate outside the prompt Safety lives in code, not prose
Agent loop turn budget + loop detection + stop conditions The loop is a control system, not a while-tool-calls toy
Eval suite data shape → required/forbidden method Test the judgment, not the prose

The judgment, made concrete

Same data, two attribution models:

from mixpilot.tools.attribution import run_attribution_model

paths  = [{"path": ["Social", "Search"], "converted": True}] * 40
paths += [{"path": ["Social"],           "converted": False}] * 20

run_attribution_model(paths, "last_touch").artifacts["share"]
# {'Search': 1.0, 'Social': 0.0}   <- the assist is thrown away
run_attribution_model(paths, "markov").artifacts["share"]
# {'Search': 0.5, 'Social': 0.5}   <- both channels are necessary

Last-touch hands Social nothing. Markov's removal effect sees that every conversion needed Social first, and splits the credit. That gap — assist value — is the entire reason multi-touch attribution exists.

Running the agent

from mixpilot import Agent
from mixpilot.agent.groq_client import GroqClient

agent = Agent(GroqClient(model="llama-3.3-70b-versatile"))  # needs GROQ_API_KEY
result = agent.run(
    "Here are 12 weeks of spend and sales for one channel ... "
    "what's the saturation point and should we spend more?"
)
print(result.final_text)

Swap GroqClient for AnthropicClient (needs ANTHROPIC_API_KEY) to run the same loop on Claude. The client is injected, so production uses a real model and the evals use a scripted client — no network needed to test the harness.

Evals: scoring method selection

python evals/run_evals.py          # offline, deterministic
python evals/run_evals.py --live   # against a real model

Each case pairs a data shape with the methods it does and does not support. A case passes only if the agent uses every required tool and avoids every forbidden one — e.g. it must not run Markov attribution on single-touch data, and must audit before claiming per-channel effects on collinear spend.

Tests

python -m pytest -q     # 14 passing — domain math, harness contracts, provider translation

The tests never call a model. They prove the adstock conserves mass, the Hill fit recovers known parameters, the Markov removal effect credits assists, the optimiser moves budget toward unsaturated channels, the audit catches multicollinearity, and the approval gate blocks mutating actions. Harness reliability that has nothing to do with model intelligence.

Scope

This is deliberately small. No context compaction, no MCP, no subagents — those are solved problems in general harnesses. The point here is the opposite: how far you get when the action space is a real domain and the tools enforce the judgment.

MIT licensed.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mixpilot-0.1.2.tar.gz (20.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mixpilot-0.1.2-py3-none-any.whl (21.8 kB view details)

Uploaded Python 3

File details

Details for the file mixpilot-0.1.2.tar.gz.

File metadata

  • Download URL: mixpilot-0.1.2.tar.gz
  • Upload date:
  • Size: 20.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.5

File hashes

Hashes for mixpilot-0.1.2.tar.gz
Algorithm Hash digest
SHA256 47e9ec5fc5a096a148a8ee62ea2c10a459078593ca320ad0b8e548fec6376105
MD5 f3c157d5f3d8b7634910b6bd051cbe36
BLAKE2b-256 c58b62ba2c43d0af613f612f4283157c341e6df3ee75c53e7ccb9f01c9223d6a

See more details on using hashes here.

File details

Details for the file mixpilot-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: mixpilot-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 21.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.5

File hashes

Hashes for mixpilot-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 cadd6745269e7ec9d3ea78ec58352ab2dbc263c1da3af58c475a9d0f437020bc
MD5 2f84d2836907f95708ef2bddaaee154d
BLAKE2b-256 0167a0a13870b549e65fbc45083cd5b8a52b474442d70bcd5a029524eff4f291

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page