This is intended as an advanced guide for those who want to understand the semantics of runs, and directly interact with the internal state of an Agent execution. For most use case, you should just use Workflows directly as it manages the run lifecycle for you.

A Run is used by the Agents to manage the lifecycle of their execution.

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.

const run = await inferable.run({
  initialPrompt: `Submit a support ticket with these details: ${details}`,
  attachedFunctions: [
    {
      function: "submitTicket",
      tools: "default",
    },
    {
      function: "sendEmail",
      tools: "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", tools: "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.

Options

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

id

The ID of the Run. If not provided, one will be generated automatically. If provided, and the run already exists, the existing run will be returned.

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.

agentId

If the configuration should be inherited from an Agent.

agentId: 'XXXXXXXX' // ID of the Agent

input

A structured input object which is merged with the initialPrompt. If the run specifies an Agent with an inputSchema, this will be validated against that schema.

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

{
  "onStatusChange": {
    "function": {
      "function": "result",
      "tools": "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"
  }
]

tags

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

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

context

Context object which is passed to all calls in the Run. This can be used to vary the behavior of functions in a Run, for example based on a timezone value.

These values are not made available to the model. To do so, add them in the initialPrompt, systemPrompt or input.

The values provided are available within a function’s second argument which also contains any authContext returned from default.handleCustomAuth.

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

const run = await inferable.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 false.

interactive

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

Defaults to true.

Messages

A Run contains a sequence of messages which will conform to the following types.

human

The human message type represents a user message within the Run which might have been added via the API the Playground, Slack, or the React SDK.

{
  id: string
  createdAt: string
  type: "human"
  data: {
    message: string
  }
}

agent

The agent message type represent an output from the model.

If the agent has requested to call a tool, the data.invocations field will be populated with the request(s).

The agent may chose to return data via the result field. If the Run has a resultSchema, the result field will conform to that schema. Otherwise, the result field will be an unstructured object.

  id: string
  createdAt: string
  type: "agent"
  data: {
    message: String
    result: Object // If a Run has a resultSchema, this will conform to that schema, Otherwise it will be an unstructured object
    invocations: [
      {
        id: String
        toolName: String
        reasoning: String // Agent provided reasoning for the tool call
        input: Object // The input the agent provided to the tool call
      }
    ]
  }
}

invocation-result

The invocation-result message type represents the output of a tool invocation.

data.result will be populated with the result of the tool’s handler (Including errors, see invocation-failure).

data.id is will refer to an individual invocation within a previous agent message ($.data.invocations.id) in the run.

The result status of an invocation-result message can be determined by the data.resultType field which will be either resolution or rejection.

  id: string
  createdAt: string
  type: "invocation-result"
  data: {
    id: String // This will match a previous invocation within an `agent` message (`$.data.invocations.id`)
    toolName: String
    resultType: "resolution" | "rejection"
    result: Object // Result returned by tool
  }
}

React SDK type mapping

By default, the React SDK will return un-typed data.result objects as these are defined by the individual tool. useMessages provides the option of passing a resultMap to map tool names to Zod schemas allowing for typed data.result to be returned.

const {
  messages: rawMessages,
} = useRun(inferable);

const messages = useMessages(rawMessages, {
  resultMap: {
    "myToolName": z.object({
        someData: z.string(),
      }))
    }),
  }
});

messages.all('asc').forEach((msg) => {
  if (msg.type === "invocation-result" && msg.data?.toolName === "myToolName") {
    // Typed myToolName result
    console.log(msg.data.result.someData)
  }
});

if (messages.error) {
  console.error("Error fetching / parsing messages:", messages.error);
}

invocation-failure

The invocation-failure message type is not currently implemented, but will be added in the future.

Currently, failures are returned as invocation-result messages with result set to the error object returned by the tool.

See Github issue for more details.

Context Limits

Large Language Models (LLMs) have fixed context windows that limit how much information they can process at once. Inferable helps manage these limitations by handling overflows automatically.

Each message (Human, Agent and function result) in a Run counts towards the total allowed context size. The maximum size is determined by the model selected for the Run.

Context Overflow

When the context size limit for a given run is reached, Inferable will truncate the message history from the beginning of the run in order to allow new message to be processed.

If any individual function result is greater then 500kb, the result will be converted into a blob and the Agent will be informed that the result was too large.