Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.simplefunctions.dev/llms.txt

Use this file to discover all available pages before exploring further.

This recipe models the split between a quant bot and a human trader:
  1. SDK gathers market, runtime, and portfolio state.
  2. Deterministic code ranks and rejects candidates.
  3. Agent SDK writes a bounded analyst note from the shortlist.
  4. Execution is a separate policy-gated call with explicit confirmation.

Quant gate first

import { SimpleFunctions } from "@spfunctions/sdk"

const sf = new SimpleFunctions({
  baseUrl: "https://simplefunctions.dev",
  apiKey: process.env.SF_API_KEY,
})

const screen = await sf.intelligence.screen({
  venue: "kalshi",
  hasOrderbook: true,
  volMin: 100,
  sort: "volume",
  order: "desc",
  limit: 20,
  nextActions: false,
})

const shortlist = []
for (const market of screen.markets.slice(0, 8)) {
  const inspected = await sf.markets.get(market.ticker, { nextActions: false })
  const spread = Number(inspected.spread ?? 99)
  const price = Number(inspected.bestAsk ?? inspected.price ?? 0)
  const cost = price

  if (spread > 5) continue
  if (price < 5 || price > 80) continue
  if (cost > 300) continue

  shortlist.push({
    ticker: inspected.ticker,
    title: inspected.title,
    bestAsk: inspected.bestAsk,
    spread,
    volume24h: inspected.volume24h,
  })
}
For a Polymarket-only workflow, screen or inspect Polymarket candidates first, then carry the CLOB tokenId into the execution plan. The same loop shape applies; only the venue identifier and compliance gates differ.

Agent note second

import { Agent, OpenRouterProvider } from "@spfunctions/agent/v1"

const analyst = await Agent.create({
  apiKey: process.env.SF_API_KEY,
  provider: new OpenRouterProvider({ apiKey: process.env.OPENROUTER_API_KEY }),
  model: { id: "anthropic/claude-haiku-4.5" },
  builtinTools: ["world.read", "market.inspect"],
  options: {
    maxTurns: 3,
    maxBudgetUsd: 0.25,
    allowedTools: ["world.read", "market.inspect"],
  },
})

const run = analyst.send([
  "Use only this shortlist and SimpleFunctions read tools.",
  "Return verdict, topTicker, thesis, invalidateIf, and whether to trade.",
  JSON.stringify({ shortlist }),
].join("\n"))

for await (const event of run.stream()) {
  console.log(event.type)
}

Policy-gated execution third

import { SimpleFunctionsAgent } from "@spfunctions/agent"

const top = shortlist[0]
const confirm = process.env.SF_TRADE_CONFIRM

if (confirm !== "operator-approved") {
  throw new Error("missing operator confirmation")
}

const executionAgent = new SimpleFunctionsAgent({
  client: sf,
  policy: {
    maxSideEffect: "live_trade",
    maxCostEffect: "venue_request_cost",
    trade: {
      allowedVenues: ["kalshi"],
      allowedTickers: [top.ticker],
      maxQuantity: 1,
      maxOrderCostCents: 300,
      requireLimitPrice: true,
      allowRuntimeStart: true,
      confirmToken: "operator-approved",
    },
  },
})

await executionAgent.tools.execution.place({
  ticker: top.ticker,
  title: top.title,
  action: "buy",
  direction: "yes",
  quantity: 1,
  limitPrice: top.bestAsk,
  rationale: "operator-approved agent trader loop",
  confirm,
})
Polymarket execution uses the same Agent SDK tool with venue and jurisdiction guardrails:
const polyExecutionAgent = new SimpleFunctionsAgent({
  client: sf,
  policy: {
    maxSideEffect: "live_trade",
    maxCostEffect: "venue_request_cost",
    trade: {
      allowedVenues: ["polymarket"],
      blockedJurisdictions: ["US", "FR"],
      requireJurisdiction: true,
      maxQuantity: 1,
      maxOrderCostCents: 300,
      requireLimitPrice: true,
      allowRuntimeStart: true,
      confirmToken: "operator-approved",
    },
  },
})

await polyExecutionAgent.tools.execution.place({
  venue: "polymarket",
  tokenId: "POLYMARKET_CLOB_TOKEN_ID",
  title: "Polymarket event outcome",
  action: "buy",
  quantity: 1,
  limitPrice: 32,
  rationale: "operator-approved agent trader loop",
  jurisdiction: "CA",
  confirm,
})

Production notes

  • Never let the model pick an unbounded ticker universe.
  • Keep execution out of the first read-only agent run.
  • Use allowedTickers, maxOrderCostCents, requireLimitPrice, and confirmToken.
  • Use allowedVenues, blockedJurisdictions, and requireJurisdiction when the workflow can touch venue-specific compliance boundaries.
  • Persist the shortlist, model note, order request, and runtime status for audit.

Next steps

SDK execution guardrails

Runtime-first SDK execution pattern.

Stability and side effects

Contract side-effect and cost classes.