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 metadataShow RegisterFunctionMessage properties
Function ID/path (use :: for namespacing, e.g., service::function_name)
Human-readable description of the function
JSON schema for input validation and documentation
JSON schema for output validation and documentation
Custom metadata attached to the function
handler
RemoteFunctionHandler<TInput, TOutput>
required
Async function that processes the input and returns outputtype RemoteFunctionHandler<TInput, TOutput> = (data: TInput) => Promise<TOutput>
Reference to the registered functionShow FunctionRef properties
Function to unregister this 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)
config
HttpInvocationConfig
required
HTTP endpoint configurationShow HttpInvocationConfig properties
method
'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'
default:"POST"
HTTP method
Request timeout in milliseconds
Authentication configuration
type
'hmac' | 'bearer' | 'api_key'
required
Authentication type
HMAC Auth:{ type: 'hmac', secret_key: string }
Bearer Token:{ type: 'bearer', token_key: string }
API Key:{ type: 'api_key', header: string, value_key: string }
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
Use namespacing for organization
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)
Add descriptions for discoverability
iii.registerFunction(
{
id: 'orders::process_payment',
description: 'Process payment for an order using Stripe'
},
handler
)
Use TypeScript generics for type safety
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()
})