Skip to content

Implementation guide

Campaigns

Define campaign templates, review plans, and retrieve results.

Browse developer docs

Current: Campaigns

Draft and approve a plan

Campaigns require unified v2 campaign routes and account access. createCampaign / create_campaign creates a draft. Review its objective, stages, and deliverables before approval; save the review_digest of that exact reviewed plan. A stale digest returns conflict. These snippets assume a validated plan and an authenticated client.

typescript

const draft = await client.createCampaign(plan, { idempotencyKey: 'discovery-001' });
// Present draft to your reviewer; persist draft.id and draft.review_digest.
// After approval of that exact plan:
const started = await client.approveCampaign(reviewedId, reviewedDigest);
const result = await client.waitCampaign(started.id);

python

draft = client.create_campaign(plan, idempotency_key="discovery-001")
# Present draft to your reviewer; persist draft["id"] and draft["review_digest"].
# After approval of that exact plan:
started = client.approve_campaign(reviewed_id, reviewed_digest)
result = client.wait_campaign(started["id"])

waitCampaign / wait_campaign returns immediately for a draft; it never approves work. It also returns on completed, failed, cancelled, or needs_attention. Inspect status and stages to decide the next action.

Define a campaign agent

Create an agent with run_mode: 'campaign', a campaign_plan, and its input_form. Template strings use {{field_label}} to insert input values. The backend validates the template and refuses undeclared placeholders or a campaign mode without a plan. getAgent returns the configuration; updateAgent can replace it. To return to ordinary runs, update with { run_mode: 'job', campaign_plan: null }.

typescript

const agent = new Agent({
  apiKey: process.env.AGENTRUN_API_KEY!,
  name: 'Company discovery',
  instructions: 'Find verifiable company information and cite evidence.',
  run_mode: 'campaign',
  input_form: [{ label: 'goal', type: 'text', required: true }],
  campaign_plan: {
    name: 'Company discovery', objective: '{{goal}}',
    stages: [
      { key: 'discover', title: 'Find companies', op: 'agent',
        instruction: 'Find companies matching this goal: {{goal}}',
        entity_key_field: 'company_website', records_field: 'companies' },
      { key: 'inspect', title: 'Verify each company', op: 'agent',
        instruction: 'Verify this company against the goal: {{goal}}. Cite evidence.',
        fanout: 'per_entity', entity_key_field: 'company_website', depends_on: ['discover'],
        output_schema: { type: 'object', properties: { evidence: { type: 'string' } } } },
      { key: 'join', title: 'Combine findings', op: 'join', depends_on: ['discover', 'inspect'] },
      { key: 'export', title: 'Export results', op: 'export', depends_on: ['join'],
        filename: 'companies.xlsx', entity_key_field: 'company_website',
        columns: ['company_website', 'company', 'evidence'], requested: 10 },
    ],
    deliverables: [{ key: 'companies', title: 'Verified companies', kind: 'dataset', from_stage: 'export' }],
  },
});
await agent.create();
const campaign = await agent.campaign({ goal: 'Find UK cloud infrastructure companies' }, {
  idempotencyKey: 'company-discovery-001',
});

This call renders and starts the configured campaign immediately. Use getCampaign(campaign.id) to inspect stage progress and download a ready artifact with downloadCampaignArtifact(campaign.id, 'companies'). The same configuration fields are accepted by MCP create_agent.

Python campaign agents

Use client.create_agent with run_mode="campaign", campaign_plan=plan, and input_form to save the same template structure shown above. Then:

python

agent = client.agent(saved_agent_id)
campaign = agent.campaign(
    {"goal": "Find UK cloud infrastructure companies"},
    records=[{"company_website": "example.com"}],
    idempotency_key="discovery-002",
)

agent.campaign in both languages renders and approves the stored template immediately. Use the draft workflow when your application requires a separate review step. records supplies optional seed records; it is separate from template inputs. Goal-to-plan generation is not implemented by these SDK methods.

Read results and download artifacts

getCampaignPortfolio / get_campaign_portfolio takes the campaign ID and stage key, with cursor, limit, status, and search filters. It returns coverage, items, and next_cursor. Follow run_id for full reports. Download by a ready deliverable's key, not its display title.

typescript

const page = await client.getCampaignPortfolio(campaign.id, 'inspect', { limit: 50 });
const blob = await client.downloadCampaignArtifact(campaign.id, 'companies');
const bytes = new Uint8Array(await blob.arrayBuffer());

python

page = client.get_campaign_portfolio(campaign["id"], "inspect", limit=50)
data = client.download_campaign_artifact(campaign["id"], "companies")
with open("companies.xlsx", "wb") as output:
    output.write(data)

cancelCampaign / cancel_campaign stops pending work. Local wait deadlines do not cancel work. Artifacts preserve their original binary bytes.