A Run is an execution that processes your task using language models and registered functions.

Runs maintain persistent state including previous function calls and message history. When interacting with the Inferable APIs or SDKs, new messages can be appended to the run.

When inferable receives a new Run, it is executed using a ReAct-like agent strategy which iteratively reasons about the task and takes actions to achieve the requested outcome. This includes calling the attached functions as necessary.

Inferable performs all model calls and gracefully handles transient errors such as timeouts. The Run is a durable execution construct which supports indefinitely long Function calls and pausing for human interaction.

const run = await inferable.run({
  initialPrompt: `Submit a support ticket with these details: ${details}`,
  attachedFunctions: [
    {
      function: "submitTicket",
      service: "default",
    },
    {
      function: "sendEmail",
      service: "default",
    },
    // ... Any other functions to make available to the run
  ],
  resultSchema: z.object({
    success: z.boolean(),
  }),
  // Optional: Subscribe an Inferable function to receive notifications when the run status changes
  // onStatusChange: { function: { function: "handler", service: "default" } },
});

At each step in the cycle, Inferable will provide details including any functions that are invoked, the reasoning for invoking a function or any issues the agent has encountered.

Lifecycle

At any given time, a Run will be in one of the following statuses, transitioning between them as it progresses:

StatusDescription
pendingThe Run has been created but not yet started processing.
runningThe Run is currently processing the agent loop.
pausedThe Run is paused (e.g., waiting for an approval).
doneThe Run has completed. A result and summary should have been produced.
failedThe Run failed. Please see failureReason for more information.

An Inferable Run can move from the done state back into running with a follow-up message or editing a previous messages to re-evaluate the run from that point.

A function failing will not cause a Run to enter the failed state. Instead, the exception will be returned to the agent for evaluation.

Similarly, a Run where the agent was not able to complete the specified task will still result in the done state.

Function Selection

If a Run is triggered without functions explicitly attached, the agent will have access to all functions registered in the cluster (including the standard library).

At each step in the Run, Inferable will perform a similarity search across all available functions considering the name, description and schema and attach the most relevant functions.

Result

Assuming a Run’s status is done the run will have a structured JSON result and/or a message depending on if a resultSchema was specified.

{
  "id": "01J8GNNHRRZA9E605BEM57A3HT",
  "name": "Inventory status",
  "status": "done",
  "summary": "I found the following items",
  "result": [
    {
      "name": "Sonic Screwdriver",
      "qty": 10
    },
    {
      "name": "Towel",
      "qty": 5
    }
    // ... more items ...
  ]
  // ... other run properties ...
}

If a Run is not able to produce a structured result, the result field will be null:

{
  "run": {
    // ... run metadata ...
    "status": "success",
    "result": null,
    "summary": "Unable to process inventory data"
  }
  // ... other fields ...
}

By default the result field’s structure is up to the model, you can explicitly specify a structure with resultSchema.

As it is possible for a Run to be continued from the done status, a run may have multuple results. When fetching a run via the API or SDK, the result will be the most recent result.

References

A Run’s result may include data from multiple functions calls.

Within the Inferable UI, clicking on individual keys in the result allows you to see where in the run that data is sourced from. This helps to guard against hallucinations, and provides a way to understand where a result is coming from.

Run references can also be accesses via the API.

We are currently exploring ways to leverage these references when invoking functions.

For example, only allowing certain function invocations if the individual arguments all have valid references.

If this is something you would find useful, please reach out to us on Discord.

Options

Valid options when creating a run with the SDK or API.

initialPrompt

An initial prompt for the run (human message) .

name

A human readable name for the run, this will be shown in the Runs pane of the Playground. If none is provided, one will be generated automatically based on the initialPrompt.

config

If the configuration should be inherited from a Run Configuration.

config: {
  id: 'XXXXXXXX' // ID of the Run Configuration
  input: {} // Optional: Structured Input
}

resultSchema

By default, a Run’s result object shape is at the discretion of the model. A specific output structure can be enforced by providing a resultSchema value in JSON Schema form.

The Run will be forced to return a result in the provided format or null if this is not possible.

"resultSchema": {
  "type": "object",
  "properties": {
    "orderId": {
      "type": "string"
    },
    "required": [
      "orderId"
    ]
  }
}

onStatusChange

As an alternative to retrieving a Run result via the API or calling the SDK’s poll() function, you can provide an Inferable function as a handler which will be called each time the status of the run changes.

Using an onStatusChange handler to receive Run results provides the same durability guarantees as any other Inferable function, this is especially helpful in the case of Runs which may take some time to complete or pause for approval.

When registering an onStatusChange handler via the SDK, the function must accept an object in the correct format. Each SDK provides a helper type for registering the onStatusChange handler

// NodeJS
import { onStatusChangeSchema } from "inferable";
const onStatusChange = client.default.register({
  name: "onStatusChangeFn",
  schema: statusChangeSchema,
  func: (input) => {},
});
// .Net
using Inferable;
var Func = new Func<OnStatusChangeInput<MyRunResult>, object?>((input) => {}),
// Go
Func := func(input OnStatusChangeInput) string {},
{
  "onStatusChange": {
    "function": {
      "function": "result",
      "service": "default"
    }
  },
}

attachedFunctions

By default, a Run will have access to all functions within the cluster (including the Standard Library, you can explicitly attach a set of desired functions by setting the attachedFunctions property.

"attachedFunctions": [
  {
    "service": "default",
    "function": "myFunctionName"
  },
  {
    "service": "inferable",
    "function": "accessKnowledgeArtifacts"
  }
]

metadata

Key-Value metadata which can be attached to the run. Runs are queryable by these values using the API. Metadata is useful for maintaining a relation between Inferable Runs and entities within your systems, for example, attaching an orderId or customerId to Runs.

"metadata": {
  "orderId": "abc-123"
}

context

Context object which is passed to all calls in the run along with any values returned from default.handleCustomerAuth

This is useful for varying the behavior of a function based on the context of the run.

client.default.register({
  name: "checkTime",
  func: async (_input, context) => {
    //{
    //  runContext: {
    //    timeZone: "Australia/Adelaide"
    //  },
    //   authContext: null
    //}
    cosnole.log(context);
  },
});

const run = await client.run({
  initialPrompt: "What is the current time?",
  context: {
    timeZone: "Australia/Adelaide",
  },
});

reasoningTraces

When enabled, the Run will produce a reasoning trace for each function call.

Defaults to true.

callSummarization

When enabled, the Run will attempt to auto-summarize functionr results that are too large (>10k characters) to include in the agent context.

Defaults to true.

interactive

When disabled, the run will not allow additional messages to be added.

Defaults to true.