Contracts
Contracts
Section titled “Contracts”Invoke services through typed contracts. Call remote APIs, workflows, and functions with schema validation and async execution support.
Loading
Section titled “Loading”local contract = require("contract")Opening a Binding
Section titled “Opening a Binding”Open a binding directly by ID:
local greeter, err = contract.open("app.services:greeter")if err then return nil, errend
local result, err = greeter:say_hello("Alice")With scope context or query parameters:
-- With scope tablelocal svc, err = contract.open("app.services:user", { tenant_id = "acme", region = "us-east"})
-- With query parameters (auto-converted: "true"→bool, numbers→int/float)local api, err = contract.open("app.services:api?debug=true&timeout=5000")
-- With call options (third argument)local inst, err = contract.open("app.services:flaky", nil, { retry = { max_attempts = 5, initial_delay = 100 }})| Parameter | Type | Description |
|---|---|---|
binding_id | string | Binding ID, supports query params |
scope | table | Context values (optional, overrides query params) |
options | table | Call options (optional) — e.g. retry.max_attempts, retry.initial_delay |
Returns: Instance, error
Getting a Contract
Section titled “Getting a Contract”Retrieve contract definition for introspection:
local c, err = contract.get("app.services:greeter")
print(c:id()) -- "app.services:greeter"
local methods = c:methods()for _, m in ipairs(methods) do print(m.name, m.description)end
local method, err = c:method("say_hello")Method Definition
Section titled “Method Definition”| Field | Type | Description |
|---|---|---|
name | string | Method name |
description | string | Method description |
input_schemas | table[] | Input schema definitions |
output_schemas | table[] | Output schema definitions |
Finding Implementations
Section titled “Finding Implementations”List all bindings that implement a contract:
local bindings, err = contract.find_implementations("app.services:greeter")
for _, binding_id in ipairs(bindings) do print(binding_id)endOr via contract object:
local c, err = contract.get("app.services:greeter")local bindings, err = c:implementations()Checking Implementation
Section titled “Checking Implementation”Check if instance implements a contract:
if contract.is(instance, "app.services:greeter") then instance:say_hello("World")endCalling Methods
Section titled “Calling Methods”Sync call - blocks until complete:
local calc, err = contract.open("app.services:calculator")
local sum, err = calc:add(10, 20)local product, err = calc:multiply(5, 6)Async Calls
Section titled “Async Calls”Add _async suffix for async execution:
local processor, err = contract.open("app.services:processor")
local future, err = processor:process_async(large_dataset)
-- Do other work...
-- Wait for resultlocal ch = future:response()local payload, ok = ch:receive()if ok then local result = payload:data()endSee Futures for future methods.
Opening via Contract
Section titled “Opening via Contract”Open binding through contract object:
local c, err = contract.get("app.services:user")
-- Default bindinglocal instance, err = c:open()
-- Specific bindinglocal instance, err = c:open("app.services:user_impl")
-- With scopelocal instance, err = c:open(nil, {user_id = 123})local instance, err = c:open("app.services:user_impl", {user_id = 123})Adding Context
Section titled “Adding Context”Create wrapper with pre-configured context:
local c, err = contract.get("app.services:user")
local wrapped = c:with_context({ request_id = ctx.get("request_id"), user_id = current_user.id})
local instance, err = wrapped:open()Call Options
Section titled “Call Options”Configure retry and other call behavior via with_options:
local c, err = contract.get("app.services:flaky")
local inst, err = c :with_options({ retry = { max_attempts = 5, initial_delay = 100 } }) :open("app.services:flaky_impl")
local result, err = inst:call()Options apply to every method call on the returned instance. Only retryable errors trigger retries; non-retryable errors surface immediately. Chainable with with_context, with_actor, with_scope.
| Option | Type | Description |
|---|---|---|
retry.max_attempts | int | Maximum attempts including the first (1 disables retry) |
retry.initial_delay | int/duration | Delay before first retry (ms or duration string) |
Security Context
Section titled “Security Context”Set actor and scope for authorization:
local security = require("security")local c, err = contract.get("app.services:admin")
local secured = c:with_actor(security.actor()):with_scope(security.scope())
local admin, err = secured:open()Permissions
Section titled “Permissions”| Permission | Resource | Functions |
|---|---|---|
contract.get | contract id | get() |
contract.open | binding id | open(), Contract:open() |
contract.implementations | contract id | find_implementations(), Contract:implementations() |
contract.call | method name | sync and async method calls |
contract.context | ”context” | Contract:with_context() |
contract.security | ”security” | Contract:with_actor(), Contract:with_scope() |
Errors
Section titled “Errors”| Condition | Kind |
|---|---|
| Invalid binding ID format | errors.INVALID |
| Contract not found | errors.NOT_FOUND |
| Binding not found | errors.NOT_FOUND |
| Method not found | errors.NOT_FOUND |
| No default binding | errors.NOT_FOUND |
| Permission denied | errors.PERMISSION_DENIED |
| Call failed | errors.INTERNAL |