Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/iii-hq/sdk/llms.txt

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

Functions are the core building blocks of III applications. They can be called by other services, triggered by events, or exposed as HTTP endpoints.

registerFunction()

Register a function with a handler that executes when the function is invoked.
const functionRef = iii.registerFunction(message, handler)
message
RegisterFunctionMessage
required
Function registration metadata
handler
RemoteFunctionHandler<TInput, TOutput>
required
Async function that processes the input and returns output
type RemoteFunctionHandler<TInput, TOutput> = (data: TInput) => Promise<TOutput>
functionRef
FunctionRef
Reference to the registered function

Example: Basic Function

import { init, getContext } from 'iii-sdk'

const iii = init('ws://localhost:49199')

const echoFn = iii.registerFunction(
  { 
    id: 'examples::echo',
    description: 'Echo back the input message'
  },
  async (data: { message: string }) => {
    const { logger } = getContext()
    logger.info('Echo called', { message: data.message })
    
    return { echoed: data.message }
  }
)

// Later: unregister
echoFn.unregister()

Example: Typed Function with Validation

interface CreateUserInput {
  email: string
  name: string
  age?: number
}

interface CreateUserOutput {
  id: string
  email: string
  name: string
  created_at: string
}

iii.registerFunction<CreateUserInput, CreateUserOutput>(
  {
    id: 'users::create',
    description: 'Create a new user',
    request_format: {
      name: 'CreateUserInput',
      type: 'object',
      body: [
        { name: 'email', type: 'string', required: true },
        { name: 'name', type: 'string', required: true },
        { name: 'age', type: 'number', required: false }
      ]
    },
    response_format: {
      name: 'CreateUserOutput',
      type: 'object',
      body: [
        { name: 'id', type: 'string', required: true },
        { name: 'email', type: 'string', required: true },
        { name: 'name', type: 'string', required: true },
        { name: 'created_at', type: 'string', required: true }
      ]
    }
  },
  async (input) => {
    const { logger, trace } = getContext()
    
    // Validate input
    if (!input.email.includes('@')) {
      throw new Error('Invalid email address')
    }
    
    const user = {
      id: crypto.randomUUID(),
      email: input.email,
      name: input.name,
      created_at: new Date().toISOString()
    }
    
    logger.info('User created', { userId: user.id })
    trace?.setAttribute('user.id', user.id)
    
    return user
  }
)

registerHttpFunction()

Register an external HTTP function (Lambda, Cloudflare Worker, etc.) that the engine invokes via HTTP.
const functionRef = iii.registerHttpFunction(id, config)
id
string
required
Function ID/path
config
HttpInvocationConfig
required
HTTP endpoint configuration
functionRef
FunctionRef
Reference to the registered HTTP function

Example: Lambda Function

iii.registerHttpFunction(
  'external::my_lambda',
  {
    url: 'https://abc123.lambda-url.us-east-1.on.aws/',
    method: 'POST',
    timeout_ms: 30000,
    headers: {
      'Content-Type': 'application/json'
    },
    auth: {
      type: 'bearer',
      token_key: process.env.LAMBDA_TOKEN!
    }
  }
)

// Call the Lambda function like any other III function
const result = await iii.call('external::my_lambda', { data: 'test' })

Example: Cloudflare Worker

iii.registerHttpFunction(
  'external::cf_worker',
  {
    url: 'https://my-worker.username.workers.dev/process',
    method: 'POST',
    headers: {
      'X-Custom-Header': 'value'
    },
    auth: {
      type: 'api_key',
      header: 'X-API-Key',
      value_key: process.env.CF_API_KEY!
    }
  }
)

Function Handler Context

All function handlers have access to a context object via getContext():
import { getContext } from 'iii-sdk'

iii.registerFunction(
  { id: 'example::handler' },
  async (data) => {
    const { logger, trace } = getContext()
    
    // Use the logger
    logger.info('Processing request', { data })
    
    // Add trace attributes
    trace?.setAttribute('custom.attribute', 'value')
    trace?.addEvent('Processing started')
    
    return { success: true }
  }
)
See Context API for full documentation.

Error Handling

Throw errors in function handlers to propagate them to callers:
iii.registerFunction(
  { id: 'users::get' },
  async (data: { id: string }) => {
    const { logger } = getContext()
    
    const user = await db.users.findUnique({ where: { id: data.id } })
    
    if (!user) {
      logger.warn('User not found', { userId: data.id })
      throw new Error(`User not found: ${data.id}`)
    }
    
    return user
  }
)

// Caller receives the error
try {
  await iii.call('users::get', { id: 'invalid' })
} catch (error) {
  console.error('Error:', error.message) // "User not found: invalid"
}

Unregistering Functions

Unregister functions when they’re no longer needed:
const fn = iii.registerFunction(
  { id: 'temp::function' },
  async (data) => ({ result: 'ok' })
)

// Later: unregister
fn.unregister()

// Or call by function ID
iii.sendMessage(MessageType.UnregisterFunction, { id: 'temp::function' })

Best Practices

Group related functions using :: separator:
// Good
iii.registerFunction({ id: 'users::create' }, handler)
iii.registerFunction({ id: 'users::update' }, handler)
iii.registerFunction({ id: 'users::delete' }, handler)

// Avoid
iii.registerFunction({ id: 'createUser' }, handler)
iii.registerFunction({ id: 'updateUser' }, handler)
iii.registerFunction(
  {
    id: 'orders::process_payment',
    description: 'Process payment for an order using Stripe'
  },
  handler
)
interface Input { /* ... */ }
interface Output { /* ... */ }

iii.registerFunction<Input, Output>(
  { id: 'my::function' },
  async (data) => {
    // data is typed as Input
    // return type must match Output
  }
)
const functions: FunctionRef[] = []

functions.push(iii.registerFunction({ id: 'fn1' }, handler1))
functions.push(iii.registerFunction({ id: 'fn2' }, handler2))

process.on('SIGTERM', async () => {
  // Unregister all functions
  functions.forEach(fn => fn.unregister())
  await iii.shutdown()
})

Build docs developers (and LLMs) love