Skip to main content
This page provides ready-to-use patterns for common agent workflows. Each example shows the complete tool sequence or SDK code an AI agent would use, with both Node.js and Python implementations.

Pattern 1: Set Up a Complete Affiliate Program

This workflow creates a program, connects Stripe, checks readiness, publishes marketplace settings, and invites the first affiliates — everything a merchant needs to go live from the REST/SDK surface.
import { AgentRef } from 'agentref';

const client = new AgentRef({ apiKey: process.env.AGENTREF_API_KEY });

// Step 1: Create the program
const program = await client.programs.create({
  name: 'Acme Pro Referrals',
  commissionType: 'recurring',
  commissionPercent: 25,
  cookieDuration: 60,
  payoutThreshold: 5000, // $50.00 in cents
  autoApproveAffiliates: true,
  currency: 'USD',
}, { idempotencyKey: 'setup-acme-pro-v1' });

console.log(`Program created: ${program.id}`);

// Step 2: Connect Stripe
const stripe = await client.programs.connectStripe(program.id);
console.log(`Complete Stripe OAuth at: ${stripe.authUrl}`);
// The merchant opens this URL in a browser to connect their Stripe account

// Step 3: Check readiness
const detail = await client.programs.get(program.id);
console.log(`Readiness: ${detail.readiness}`);

// Step 4: Publish to marketplace
await client.programs.updateMarketplace(program.id, {
  status: 'public',
  category: 'SaaS',
  description: 'Earn 25% recurring commission on every referral.',
});

// Step 5: Invite affiliates
const invite = await client.programs.createInvite(program.id, {
  email: 'top-affiliate@example.com',
  name: 'Top Affiliate',
  expiresInDays: 14,
}, { idempotencyKey: 'invite-top-affiliate-v1' });

console.log(`Invite sent: ${invite.token}`);

// Step 6: Create a public invite link for broader distribution
const publicInvite = await client.programs.createInvite(program.id, {
  isPublic: true,
  usageLimit: 100,
  expiresInDays: 30,
}, { idempotencyKey: 'public-invite-v1' });
from agentref import AgentRef

client = AgentRef()  # reads AGENTREF_API_KEY from env

# Step 1: Create the program
program = client.programs.create(
    name="Acme Pro Referrals",
    commission_type="recurring",
    commission_percent=25,
    cookie_duration=60,
    payout_threshold=5000,  # $50.00 in cents
    auto_approve_affiliates=True,
    currency="USD",
    idempotency_key="setup-acme-pro-v1",
)
print(f"Program created: {program.id}")

# Step 2: Connect Stripe
stripe = client.programs.connect_stripe(program.id)
print(f"Complete Stripe OAuth at: {stripe.auth_url}")

# Step 3: Check readiness
detail = client.programs.get(program.id)
print(f"Readiness: {detail.readiness}")

# Step 4: Publish to marketplace
client.programs.update_marketplace(
    program.id,
    status="public",
    category="SaaS",
    description="Earn 25% recurring commission on every referral.",
)

# Step 5: Invite affiliates
invite = client.programs.create_invite(
    program.id,
    email="top-affiliate@example.com",
    name="Top Affiliate",
    expires_in_days=14,
    idempotency_key="invite-top-affiliate-v1",
)
print(f"Invite sent: {invite.token}")

# Step 6: Public invite link
public_invite = client.programs.create_invite(
    program.id,
    is_public=True,
    usage_limit=100,
    expires_in_days=30,
    idempotency_key="public-invite-v1",
)

Pattern 2: Monitor Conversions and Flag Fraud

This workflow checks recent conversions, reviews fraud flags, and takes action on suspicious activity. Ideal for a scheduled agent task.
import { AgentRef } from 'agentref';

const client = new AgentRef({ apiKey: process.env.AGENTREF_API_KEY });

// Step 1: Check conversion stats for the last 7 days
const stats = await client.conversions.stats({ period: '7d' });
console.log(`Last 7 days: ${stats.total} conversions, $${stats.totalRevenue / 100} revenue`);
console.log(`Pending: ${stats.pending}, Approved: ${stats.approved}`);

// Step 2: List recent conversions that need review
const { data: conversions } = await client.conversions.list({
  status: 'pending',
  limit: 50,
});

console.log(`${conversions.length} pending conversions to review`);

// Step 3: Check for open fraud flags
const flagStats = await client.flags.stats();
console.log(`Open fraud flags: ${flagStats.open}`);

if (flagStats.open > 0) {
  const { data: flags } = await client.flags.list({
    status: 'open',
    limit: 20,
  });

  for (const flag of flags) {
    console.log(`Flag ${flag.id}: ${flag.type} for affiliate ${flag.affiliateId}`);

    // Step 4: Auto-dismiss low-risk flags, escalate high-risk
    if (flag.type === 'high_click_frequency') {
      // Get the affiliate's full stats for context
      const affiliate = await client.affiliates.get(flag.affiliateId, {
        include: 'stats',
      });

      if (affiliate.totalConversions > 0) {
        // Has real conversions -- likely legitimate traffic
        await client.flags.resolve(flag.id, {
          status: 'dismissed',
          note: `Auto-dismissed: ${affiliate.totalConversions} conversions confirm legitimate traffic`,
          blockAffiliate: false,
        }, { idempotencyKey: `resolve-${flag.id}` });
      } else {
        // No conversions -- suspicious, confirm the flag
        await client.flags.resolve(flag.id, {
          status: 'confirmed',
          note: 'Zero conversions with high click volume -- confirmed suspicious',
          blockAffiliate: true,
        }, { idempotencyKey: `resolve-${flag.id}` });
      }
    }
  }
}
from agentref import AgentRef

client = AgentRef()

# Step 1: Check conversion stats for the last 7 days
stats = client.conversions.stats(period="7d")
print(f"Last 7 days: {stats.total} conversions, ${stats.total_revenue / 100} revenue")
print(f"Pending: {stats.pending}, Approved: {stats.approved}")

# Step 2: List recent conversions that need review
result = client.conversions.list(status="pending", limit=50)
print(f"{len(result.data)} pending conversions to review")

# Step 3: Check for open fraud flags
flag_stats = client.flags.stats()
print(f"Open fraud flags: {flag_stats.open}")

if flag_stats.open > 0:
    flags_result = client.flags.list(status="open", limit=20)

    for flag in flags_result.data:
        print(f"Flag {flag.id}: {flag.type} for affiliate {flag.affiliate_id}")

        # Step 4: Auto-dismiss low-risk flags, escalate high-risk
        if flag.type == "high_click_frequency":
            affiliate = client.affiliates.get(flag.affiliate_id, include="stats")

            if affiliate.total_conversions > 0:
                client.flags.resolve(
                    flag.id,
                    status="dismissed",
                    note=f"Auto-dismissed: {affiliate.total_conversions} conversions confirm legitimate traffic",
                    block_affiliate=False,
                    idempotency_key=f"resolve-{flag.id}",
                )
            else:
                client.flags.resolve(
                    flag.id,
                    status="confirmed",
                    note="Zero conversions with high click volume -- confirmed suspicious",
                    block_affiliate=True,
                    idempotency_key=f"resolve-{flag.id}",
                )

Pattern 3: Generate Weekly Payout Report

This workflow lists pending payouts, aggregates stats, and generates a report. Useful for weekly cron jobs or scheduled agent tasks.
import { AgentRef } from 'agentref';

const client = new AgentRef({ apiKey: process.env.AGENTREF_API_KEY });

// Step 1: Get payout stats
const payoutStats = await client.payouts.stats({ period: '30d' });
console.log(`Total paid (30d): $${payoutStats.totalPaid / 100}`);
console.log(`Total pending: $${payoutStats.totalPending / 100}`);

// Step 2: List all pending affiliates across programs
const pending = await client.payouts.listPending();

const report = {
  generatedAt: new Date().toISOString(),
  totalPending: pending.meta.total,
  affiliates: pending.data.map(aff => ({
    name: aff.name ?? aff.email,
    program: aff.programName,
    amount: `$${aff.pendingAmount / 100}`,
    currency: aff.currency,
    method: aff.payoutMethod ?? 'Not set',
    meetsThreshold: aff.meetsThreshold,
    commissionCount: aff.commissionCount,
  })),
};

console.log('--- Weekly Payout Report ---');
console.log(JSON.stringify(report, null, 2));

// Step 3: For affiliates who meet the threshold and have a payout method,
// create the payout
const eligible = pending.data.filter(
  aff => aff.meetsThreshold && aff.hasPayoutMethod
);

console.log(`\n${eligible.length} affiliates eligible for payout`);

for (const aff of eligible) {
  const payout = await client.payouts.create({
    affiliateId: aff.affiliateId,
    programId: aff.programId,
    method: aff.payoutMethod!,
    notes: `Weekly payout - ${new Date().toISOString().split('T')[0]}`,
  }, { idempotencyKey: `weekly-payout-${aff.affiliateId}-${Date.now()}` });

  console.log(`Created payout for ${aff.name}: $${aff.pendingAmount / 100}`);
}

// Step 4: Get recent completed payouts for the report footer
const { data: recentPayouts } = await client.payouts.list({
  status: 'completed',
  limit: 10,
});

console.log(`\nRecent completed payouts: ${recentPayouts.length}`);
from datetime import datetime
from agentref import AgentRef

client = AgentRef()

# Step 1: Get payout stats
payout_stats = client.payouts.stats(period="30d")
print(f"Total paid (30d): ${payout_stats.total_paid / 100}")
print(f"Total pending: ${payout_stats.total_pending / 100}")

# Step 2: List all pending affiliates across programs
pending = client.payouts.list_pending()

report = {
    "generated_at": datetime.now().isoformat(),
    "total_pending": pending.meta.total,
    "affiliates": [
        {
            "name": aff.name or aff.email,
            "program": aff.program_name,
            "amount": f"${aff.pending_amount / 100}",
            "currency": aff.currency,
            "method": aff.payout_method or "Not set",
            "meets_threshold": aff.meets_threshold,
            "commission_count": aff.commission_count,
        }
        for aff in pending.data
    ],
}

print("--- Weekly Payout Report ---")
import json
print(json.dumps(report, indent=2))

# Step 3: Create payouts for eligible affiliates
eligible = [
    aff for aff in pending.data
    if aff.meets_threshold and aff.has_payout_method
]

print(f"\n{len(eligible)} affiliates eligible for payout")

today = datetime.now().strftime("%Y-%m-%d")
for aff in eligible:
    payout = client.payouts.create(
        affiliate_id=aff.affiliate_id,
        program_id=aff.program_id,
        method=aff.payout_method,
        notes=f"Weekly payout - {today}",
        idempotency_key=f"weekly-payout-{aff.affiliate_id}-{today}",
    )
    print(f"Created payout for {aff.name}: ${aff.pending_amount / 100}")

# Step 4: Recent completed payouts
recent = client.payouts.list(status="completed", limit=10)
print(f"\nRecent completed payouts: {len(recent.data)}")

Idempotency Patterns for Safe Agent Retries

AI agents may retry operations due to timeouts, network failures, or tool-calling loops. Idempotency keys ensure these retries are safe.

Deterministic Keys

Generate idempotency keys from the operation’s intent, not random values:
// Good: deterministic key based on intent
const key = `create-program-${programName}-${Date.now()}`;

// Better: based on a stable external identifier
const key = `invite-${email}-to-${programId}`;

// Best: includes a version for intentional re-runs
const key = `setup-acme-program-v2`;
# Good: deterministic key based on intent
key = f"create-program-{program_name}-{int(time.time())}"

# Better: based on a stable external identifier
key = f"invite-{email}-to-{program_id}"

# Best: includes a version for intentional re-runs
key = "setup-acme-program-v2"

Retry-Safe Workflows

When chaining multiple operations, use a unique key for each step:
const workflowId = 'onboard-acme-2026-03';

// Each step gets its own scoped key
const program = await client.programs.create({
  name: 'Acme Referrals',
  commissionType: 'recurring',
  commissionPercent: 25,
}, { idempotencyKey: `${workflowId}-create-program` });

await client.programs.createInvite(program.id, {
  email: 'partner@example.com',
}, { idempotencyKey: `${workflowId}-invite-partner` });

// Review pending applications through the Applications API or MCP review_application tool.
// Use a separate key such as `${workflowId}-approve-application-${applicationId}`.
workflow_id = "onboard-acme-2026-03"

# Each step gets its own scoped key
program = client.programs.create(
    name="Acme Referrals",
    commission_type="recurring",
    commission_percent=25,
    idempotency_key=f"{workflow_id}-create-program",
)

client.programs.create_invite(
    program.id,
    email="partner@example.com",
    idempotency_key=f"{workflow_id}-invite-partner",
)

# Review pending applications through the Applications API or MCP review_application tool.
# Use a separate key such as f"{workflow_id}-approve-application-{application_id}".

Error Handling Patterns

Graceful Degradation

When an agent encounters an error, it should attempt recovery before giving up:
import { AgentRef, NotFoundError, RateLimitError, AgentRefError } from 'agentref';

const client = new AgentRef();

async function safeGetProgram(id: string) {
  try {
    return await client.programs.get(id);
  } catch (error) {
    if (error instanceof NotFoundError) {
      // Program doesn't exist -- list all programs and pick the first
      const { data } = await client.programs.list({ status: 'active', limit: 1 });
      return data[0] ?? null;
    }
    if (error instanceof RateLimitError) {
      // Wait and retry
      await new Promise(r => setTimeout(r, error.retryAfter * 1000));
      return await client.programs.get(id);
    }
    throw error;
  }
}

async function safeResolveFlag(flagId: string) {
  try {
    await client.flags.resolve(flagId, {
      status: 'reviewed',
      note: 'Reviewed by automated agent',
    }, { idempotencyKey: `auto-review-${flagId}` });
    return { success: true };
  } catch (error) {
    if (error instanceof AgentRefError) {
      return {
        success: false,
        error: error.code,
        message: error.message,
        requestId: error.requestId,
      };
    }
    throw error;
  }
}
from agentref import AgentRef, NotFoundError, RateLimitError, AgentRefError
import time

client = AgentRef()


def safe_get_program(program_id: str):
    try:
        return client.programs.get(program_id)
    except NotFoundError:
        # Program doesn't exist -- list all and pick the first
        result = client.programs.list(status="active", limit=1)
        return result.data[0] if result.data else None
    except RateLimitError as e:
        # Wait and retry
        time.sleep(e.retry_after)
        return client.programs.get(program_id)


def safe_resolve_flag(flag_id: str):
    try:
        client.flags.resolve(
            flag_id,
            status="reviewed",
            note="Reviewed by automated agent",
            idempotency_key=f"auto-review-{flag_id}",
        )
        return {"success": True}
    except AgentRefError as e:
        return {
            "success": False,
            "error": e.code,
            "message": str(e),
            "request_id": e.request_id,
        }

Logging and Observability

Always capture the requestId from errors for debugging:
try {
  await client.conversions.list({ status: 'invalid_status' });
} catch (error) {
  if (error instanceof AgentRefError) {
    console.error(`AgentRef error [${error.requestId}]: ${error.code} - ${error.message}`);
    // Send to your observability platform
    sentry.captureException(error, {
      extra: { requestId: error.requestId, code: error.code },
    });
  }
}