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 guide starts from a blank TypeScript project and ends with:
  • SDK install
  • strict manifest inspection
  • API-keyed world.read
  • Agent v0 direct tool execution
  • Agent v0 streaming
  • local trace record/replay
  • Agent v1 query()
  • semi-realtime watch

1. Install

npm init -y
npm install @spfunctions/sdk@0.1.0-alpha.0 @spfunctions/agent@0.1.0-alpha.0
Use Node 18 or newer.

2. Set Keys

For SDK data calls and Agent live execution:
export SF_API_KEY="sf_..."
For Agent v1 model-loop examples:
export OPENROUTER_API_KEY="..."
Do not put long-lived keys in browser bundles. Use these packages from server-side TypeScript, background jobs, local agent harnesses, or trusted notebooks.

3. Inspect The Strict Contract Without A Key

/api/contracts/tools is the SDK and Agent contract truth.
import { SimpleFunctions } from "@spfunctions/sdk"

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

const manifest = await sf.manifest.list()
const world = await sf.manifest.get("world.read")
const legacy = await sf.manifest.get("get_world_state")

console.log(manifest.schemaVersion)
console.log(world?.name)
console.log(legacy)
Expected:
0.3.0-draft
world.read
null
get_world_state is a broad compatibility name, not a canonical SDK/Agent tool.

4. Make The First SDK Data Call

import { SimpleFunctions } from "@spfunctions/sdk"

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

const world = await sf.world.get()

console.log(world.asOf)
console.log(world.regime?.label)
console.log(world.salient?.slice(0, 3).map(item => item.label))
If no API key is configured, this call throws MissingApiKeyError because world.read is cost-bearing and not anonymously allowlisted.

5. Search And Inspect Markets

const search = await sf.markets.search({
  query: "Fed CPI",
  venue: "kalshi",
  limit: 5,
})

for (const market of search.markets ?? []) {
  console.log(market.ticker, market.title, market.price)
}

const firstTicker = search.markets?.[0]?.ticker
if (firstTicker) {
  const detail = await sf.markets.get(firstTicker)
  const history = await sf.markets.history(firstTicker)
  console.log(detail.title)
  console.log(history)
}

6. Handle Errors

import {
  MissingApiKeyError,
  PermissionDeniedError,
  SimpleFunctionsRateLimitError,
} from "@spfunctions/sdk"

try {
  await sf.theses.list()
} catch (error) {
  if (error instanceof MissingApiKeyError) {
    console.error("missing key", error.tool, error.reason)
  } else if (error instanceof PermissionDeniedError) {
    console.error("permission denied", error.requestId)
  } else if (error instanceof SimpleFunctionsRateLimitError) {
    console.error("rate limited")
  } else {
    throw error
  }
}

7. Create An Agent v0 Direct Runner

import { SimpleFunctions } from "@spfunctions/sdk"
import { SimpleFunctionsAgent } from "@spfunctions/agent"

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

const agent = new SimpleFunctionsAgent({
  client: sf,
  policy: {
    maxSideEffect: "none",
    maxCostEffect: "api_cost",
  },
})
The policy above allows world.read and other normal API-cost read calls. It blocks search, venue, and LLM-cost tools unless you raise maxCostEffect.

8. Call A Canonical Tool

const result = await agent.call("world.read", {})
console.log(result.tool)
console.log(result.output)
Typed wrapper:
const result = await agent.tools.world.read({})
Streaming:
for await (const event of agent.stream("world.read", {})) {
  console.log(event.type, event.runId, event.callId)
}

9. Use Typed Tool Inputs

import type { AgentToolInput, AgentToolName } from "@spfunctions/agent"

const name: AgentToolName = "markets.search"

const input: AgentToolInput<"markets.search"> = {
  query: "oil geopolitics",
  limit: 5,
}

const searchAgent = new SimpleFunctionsAgent({
  client: sf,
  policy: {
    maxSideEffect: "none",
    maxCostEffect: "search_cost",
  },
})

await searchAgent.call(name, input)

10. Record And Replay A Trace

import { FileTraceStore, ReplayMissError } from "@spfunctions/agent"

const trace = new FileTraceStore("./sf-agent.trace.jsonl")

await agent.tools.world.read({}, { trace })

const replay = new SimpleFunctionsAgent({
  client: new SimpleFunctions({ baseUrl: "https://simplefunctions.dev" }),
  mode: "replayOnly",
  trace: new FileTraceStore("./sf-agent.trace.jsonl"),
})

const replayed = await replay.tools.world.read({})
console.log(replayed.replayed)

try {
  await replay.tools.world.delta({ since: "1h" })
} catch (error) {
  if (error instanceof ReplayMissError) {
    console.log("Replay miss. No live call was made.")
  }
}

11. Run Agent v1 Query

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

const provider = new OpenRouterProvider({
  apiKey: process.env.OPENROUTER_API_KEY,
})

for await (const message of query({
  prompt: "Summarize what prediction markets imply about Fed cuts.",
  options: {
    provider,
    model: "anthropic/claude-haiku-4.5",
    maxTurns: 3,
    maxBudgetUsd: 0.25,
  },
})) {
  console.log(message.type)
}

12. Give v1 SimpleFunctions Tools

import { createSimpleFunctionsBuiltinTools, query } from "@spfunctions/agent/v1"

const tools = createSimpleFunctionsBuiltinTools(sf)

for await (const message of query({
  prompt: "Find markets related to inflation and explain the top signal.",
  options: {
    provider,
    tools,
    allowedTools: ["markets.search", "market.inspect", "world.read"],
    maxTurns: 4,
    maxBudgetUsd: 0.50,
  },
})) {
  console.log(message.type)
}

13. Watch Semi-realtime Inputs

import { watch } from "@spfunctions/agent/v1"

for await (const tick of watch.ticks({
  tickers: ["KXEXAMPLE"],
  cadence: "5min",
  cycles: 1,
})) {
  console.log(tick.ticker, tick.price, tick.delta)
}
Watch sources can also feed query():
for await (const message of query({
  prompt: "React to these ticks and inspect anything surprising.",
  options: {
    provider,
    watch: [
      { kind: "ticks", tickers: ["KXEXAMPLE"], cadence: "5min" },
    ],
    tools: createSimpleFunctionsBuiltinTools(sf),
    allowedTools: ["market.inspect", "world.read"],
    maxTurns: 4,
  },
})) {
  console.log(message.type)
}

14. Remember The Boundaries

SurfaceScope
@spfunctions/sdkTyped data and contract client
@spfunctions/agent v0Governed direct runner
@spfunctions/agent/v1Alpha model-loop runtime
sf agent --toolCLI wrapper for direct tool semantics
/api/contracts/toolsStrict canonical SDK/Agent truth
/api/toolsBroad hosted compatibility inventory
MCPBroad client adapter, not SDK truth
The alpha packages do not expose every CLI command, every API route, or every MCP tool. They expose the strict governed subset first.