Skip to main content

Execution

Execution is the process BindAI uses to run an agent against an input and produce a result. An execution can involve the configured model, instructions, tools, memory, knowledge, retrieval, middleware, conversation context, execution configuration, and event handling depending on how the agent is configured. The main application-facing execution interfaces are run(), chat(), and the streaming methods.

Running an Agent

A basic execution starts with agent.run():
The primary execution call accepts a message and can optionally receive an output type for structured results:
The first argument is the user message. The optional output argument specifies a Python type that BindAI attempts to construct from the model’s JSON response.

Execution Result

agent.run() returns an AgentResult when the execution pipeline completes normally.
The result provides an application-facing interface for accessing the generated output and checking the reported result state. A typical application can therefore use:
This keeps normal application-level result handling independent of the underlying model provider. Runtime exceptions are different from a normal unsuccessful result. If an exception escapes the execution pipeline, BindAI invokes the agent error callbacks and then re-raises the exception.

Structured Output

Execution can return structured results instead of plain text. For example, a Pydantic model can define the expected structure:
Pass the type to run():
During the finish stage, BindAI attempts to:
  1. Parse the model response as JSON.
  2. Pass the resulting mapping to the requested output type.
  3. Return the constructed object when this succeeds.
For example:
If JSON parsing or construction of the requested output type fails, BindAI falls back to the original response text rather than raising a structured-output parsing exception from the finish step. Structured output is therefore useful when downstream application code expects a predictable object, but applications should still account for the possibility of receiving the raw model response.

Tool Execution

Agents can be configured with tools. For example:
Tools become part of the agent’s execution capabilities. A model may request a registered tool during execution. BindAI then executes the requested tool and feeds the resulting tool message back into the ongoing agent execution. Conceptually:
The model can therefore perform multiple tool/model interaction cycles during a single agent execution.

Execution Pipeline

Normal agent execution uses a pipeline with the following stages:
The initialization, knowledge, and memory stages prepare the conversation and execution state. The model-generation and tool-execution stages form a loop:
The loop continues until either:
  • the model produces a response without tool calls, or
  • the configured maximum tool-iteration count is reached.
The default max_tool_iterations value is 10.

Initialization

The initialization stage prepares the execution state from the current agent and execution context. The user’s input is obtained from the execution context and added as a user message. If the agent has system instructions and the conversation does not already contain messages, the instructions are added as a system message. The execution state then contains a ModelRequest built from the current conversation and the definitions of the registered tools. Conceptually:

Knowledge

If an agent has a retriever or knowledge component, the knowledge stage can retrieve information relevant to the current user input. For example:
or:
When relevant documents are found, BindAI combines their content and adds it to the conversation as a system message:
The resulting conversation is then available to the model during the next generation step. If no knowledge or retriever is configured, this stage does not add anything to the conversation.

Memory

Memory can be attached to an agent:
Or configured when building the agent:
During execution, the memory stage attempts to read the __context__ memory record. When a memory record is available, BindAI adds its value to the conversation as a system message:
After normal execution reaches the finish stage, BindAI persists the conversation transcript under the __context__ memory key when memory is configured. The stored transcript is built from the conversation messages involved in the execution. Memory is therefore distinct from the current conversation object: memory provides persisted context that can be loaded into a later execution.

Conversation Context

Agent execution incorporates the current conversation into the model request. A conversational execution can conceptually combine:
Conversation context and long-term memory are related but distinct. Conversation represents the messages currently held by the agent, while memory can provide information persisted independently of a particular execution. Tool calls and tool results are also represented in the conversation used to build subsequent model requests. This allows later model iterations to receive the results of tools executed earlier in the same execution.

Knowledge and Retrievers

Knowledge can be attached to an agent:
Or configured through the builder:
Agents can also use a retriever directly:
Or through the builder:
The execution engine checks the retriever first. If no retriever is configured, it can use the configured knowledge component. Retrieved information is incorporated into the conversation as relevant knowledge before model generation. The exact retrieval behavior depends on the configured knowledge and retrieval implementations.

Retrieval-Augmented Generation

Knowledge and retrieval can be combined with agent execution to implement Retrieval-Augmented Generation. A typical execution flow is:
This allows an agent to use information retrieved from an application’s knowledge sources rather than relying only on information already available to the model.

Tool Execution Loop

When a model response contains tool calls, BindAI enters the tool-execution stage. For each requested tool call, BindAI:
  1. Adds the assistant’s tool-call message to the conversation.
  2. Executes the requested tool.
  3. Converts the tool result into a tool message.
  4. Adds the tool message to the conversation.
  5. Rebuilds the next model request from the updated conversation.
  6. Increments the execution iteration count.
  7. Returns to model generation.
Conceptually:
This allows an agent to perform multi-step tool interactions rather than treating a tool call as the end of execution.

Multiple Tool Calls

A model response can request multiple tools during the same execution step. For example:
BindAI processes each requested tool call and adds the resulting tool messages to the conversation. The next model request is then constructed from the updated conversation, allowing the model to use the combined tool results. The exact number of requested tools depends on the model response and the tools available to the agent.

Tool Execution Failures

Tool execution can fail. A failed tool execution is preserved as explicit tool-result content rather than being silently represented as a successful value. For example:
The failure information is added to the conversation as the tool result so that the model can receive it during the next execution step. Conceptually:
This is important because a tool failure is represented differently from a successful tool call. The model can receive the failure and determine how to continue. Depending on the model response and available tools, it may retry, use another tool, adjust the request, or produce a final response explaining the problem. Tool failures therefore do not automatically terminate the complete agent execution.

Tool Iterations

Tool-using agents may perform multiple model/tool interaction cycles during a single execution. BindAI controls this loop through AgentConfiguration.max_tool_iterations. The default value is:
The pipeline checks the iteration count before another tool cycle is started. When the maximum is reached, the execution proceeds to the finish stage using the current model response. A typical execution can therefore look like:
Tool iteration limits are useful for putting a deterministic boundary around repeated model/tool interactions.

Middleware

Middleware provides reusable execution behavior. Attach middleware directly:
Or configure it through the builder:
During normal execution, middleware is invoked around the execution pipeline. Before execution, middleware receives the agent and execution context. After successful execution, middleware is invoked in reverse registration order with the resulting AgentResult. Middleware is useful for cross-cutting concerns such as:
  • Logging
  • Authentication
  • Telemetry
  • Metrics
  • Request processing
  • Response processing
  • Other reusable execution behavior
Middleware allows these concerns to remain separate from the core agent instructions and application logic.

Execution Context

Some BindAI execution APIs operate with an ExecutionContext. For example, the low-level stream() API accepts an execution context:
The execution context contains runtime variables used by the execution pipeline. For normal message-based execution, BindAI creates the execution context internally. Context-aware APIs are useful when integrating agents with larger application or workflow runtimes where execution-specific variables need to be passed into the agent.

Streaming

BindAI exposes streaming APIs for execution. The low-level stream() method accepts an ExecutionContext:
For conversational applications, BindAI also provides stream_chat():
stream_chat() creates the execution context from the supplied message, while stream() operates on an existing execution context. Streaming uses a separate execution pipeline:
Unlike normal execution, the streaming pipeline does not run the normal tool-execution or finish stages. The model stream is obtained directly from the configured provider and returned as an iterator. This means streaming should be treated differently from normal run() or chat() execution: the application consumes provider output progressively rather than receiving a completed AgentResult from the streaming pipeline. Common streaming use cases include:
  • Chat interfaces
  • Interactive applications
  • Long-running responses
  • Real-time user interfaces

Chat Execution

BindAI also provides a chat() method:
chat() can accept an optional structured-output type:
run() delegates to the same conversational execution path used by chat(). Use the execution interface that best matches the application’s interaction model. For conversational applications, chat() can be combined with the agent’s conversation, memory, knowledge, and tool capabilities.

Events

Agents expose an event bus through agent.events. For example, an application can subscribe to tool execution events:
The execution engine publishes lifecycle events around execution:
Model generation publishes:
Tool execution publishes:
The corresponding event classes include:
  • AgentStartedEvent
  • AgentFinishedEvent
  • ModelRequestEvent
  • ModelResponseEvent
  • ToolExecutedEvent
The event bus is synchronous. Subscribers are called when an event is published. If an event handler raises an exception, the event bus logs the handler failure and continues processing rather than propagating the handler exception through the publisher. Events contain an event ID and UTC timestamp, and can also carry a payload. The event bus is distinct from the agent’s lifecycle callback API. The agent callback API uses:
The event bus uses event objects and event-name subscriptions:
The event system can be used for:
  • Monitoring
  • Logging
  • Analytics
  • Auditing
  • Observability
  • Notifications
  • Automation integrations

Hooks and Callbacks

Agents expose lifecycle and callback mechanisms for execution-related behavior. The built-in lifecycle callbacks include:
  • before_run
  • after_run
  • error
For example:
During normal execution:
  1. before_run is called before the execution pipeline.
  2. Middleware before_execute hooks run.
  3. The execution pipeline runs.
  4. Middleware after_execute hooks run after successful execution.
  5. after_run is called after successful execution.
If execution raises an exception, the agent’s error callback is invoked and the exception is then re-raised. Hooks can also be registered through:
Agent hooks are invoked when the finish stage produces an AgentResult. Hooks and callbacks can be used for:
  • Custom logging
  • Notifications
  • Auditing
  • Metrics
  • External integrations
  • Debugging
Hooks should generally remain focused on cross-cutting behavior rather than containing the application’s core business logic.

Execution Configuration

BindAI exposes execution configuration through AgentConfiguration. The available settings include:
The most directly execution-specific setting is max_tool_iterations, which limits repeated model/tool cycles. temperature and max_tokens provide model-generation configuration. stream and verbose are available as configuration fields, while the explicit streaming APIs provide the streaming execution path. Execution configuration should be kept separate from behavioral instructions whenever possible. For example, instructions should describe what an agent should do, while execution configuration can control runtime behavior and limits.

Execution and Projects

Agents can be organized as part of a BindAI project. Project configuration can provide the surrounding application structure for:
  • Agents
  • Tools
  • Workflows
  • Knowledge
  • Memory
  • Templates
  • Tests
  • Application configuration
The recommended agent API is Agent.builder(). For example:
Projects can also provide provider and model configuration through bindai.toml. When an agent is built from project configuration, the builder can load the project runtime configuration and resolve the configured provider and model. Project-scoped provider connections can also be selected through project configuration. For example:
This allows provider credentials to be selected by connection name while keeping the credential itself outside the project configuration file.

Execution and Workflows

Agents can participate in larger workflows. A workflow can coordinate agent execution with operations such as:
  • Conditions
  • Loops
  • Parallel execution
  • Retries
  • Timeouts
  • Human tasks
  • Scheduling
This allows individual agents to remain focused on specific responsibilities while workflows handle higher-level orchestration. Conceptually:
A workflow is useful when execution requires multiple explicit stages or control-flow decisions.

Execution and Multi-Agent Systems

Agent execution can also be combined with delegation and multi-agent patterns. A primary agent can delegate work to specialist agents:
Each specialist can perform its own execution while the larger system coordinates the overall task. BindAI also provides agent-group and process abstractions for explicit multi-agent task execution. For example, independent tasks can be represented conceptually as:
Parallel processes can execute independent tasks concurrently:
Tasks can also be arranged sequentially when one task depends on another:
These multi-agent execution patterns are separate from the single-agent model/tool execution loop described earlier.

Execution and External Tools

Agent execution can interact with external systems through tools and connection integrations. Connections provide integration infrastructure, while tools can expose appropriate external operations to an agent. This keeps external service logic separate from the agent’s core execution behavior. For example:
The exact external integrations available depend on the connection and tool packages installed in the project.

Execution and MCP

BindAI also supports MCP connections and MCP-discovered tools. MCP tools can become part of an agent’s available execution capabilities. The MCP integration provides functionality around:
  • MCP client connections
  • Tool discovery
  • Tool calling
  • MCP tools exposed as BindAI tools
  • Connection handling
This allows an agent to use capabilities provided by compatible MCP services. From the execution perspective, an MCP-discovered tool participates in the same general tool-call cycle as other registered tools.

Error Handling

Normal execution should check the returned AgentResult when application behavior depends on the result state.
This keeps application-level result handling independent from provider-specific response formats. Applications should decide how normal result failures are surfaced, retried, logged, or returned to users based on their requirements. Runtime exceptions are handled differently. When an exception escapes the execution pipeline:
  1. BindAI invokes the agent’s error callback.
  2. The exception is re-raised.
  3. The AgentFinishedEvent is still published through the execution engine’s finally block.
Therefore, applications should use both normal AgentResult handling and appropriate exception handling when execution reliability is important. Tool execution failures are handled separately inside the tool-execution cycle. They are converted into tool-result information so that the model can receive the failure and decide how to continue.

Execution Boundaries

Agent execution can involve multiple components:
When tools are involved, the model/tool portion of execution can contain additional cycles:
Keeping these responsibilities separate makes execution easier to understand and maintain. For example:
  • Instructions define behavior.
  • Conversation provides interaction context.
  • Memory provides persisted information.
  • Knowledge and retrieval provide external information.
  • Tools provide actions.
  • Middleware provides reusable execution behavior.
  • The model provider performs model inference.
  • AgentResult provides the application-facing result for normal completed execution.

A Complete Execution Example

The following example combines basic agent execution with a tool:
During execution, the model may request the search tool. BindAI executes the tool, records its result, and continues model execution with the updated conversation. The same agent can later be extended with additional capabilities:
This allows the execution layer to grow with the application while keeping the primary agent interface consistent.

Execution Best Practices

  • Use run() for general agent execution.
  • Use chat() for conversational execution.
  • Use stream() or stream_chat() when output needs to be processed progressively.
  • Use structured output when downstream code requires predictable data, while accounting for raw-response fallback.
  • Configure reasonable max_tool_iterations limits for tool-using agents.
  • Treat tool failures as execution information rather than assuming every tool call succeeds.
  • Use memory when persisted information is required.
  • Use knowledge and retrievers for external information.
  • Use middleware for reusable cross-cutting behavior.
  • Use hooks and callbacks for lifecycle integrations.
  • Use the event bus for event-driven integrations and observability.
  • Check AgentResult.success when normal execution failure needs to be handled explicitly.
  • Catch runtime exceptions when provider, middleware, callback, or other execution failures must be handled by the application.
  • Keep runtime configuration separate from behavioral instructions.
  • Use workflows when multiple agents or execution stages need to be coordinated.
  • Use explicit multi-agent processes when multi-agent work should be represented as structured tasks.
  • Use parallel execution only when tasks can safely run concurrently.
  • Use task dependencies when one task requires the result of another.
  • Keep external integrations behind connections or tools.
  • Use MCP when an external MCP service provides capabilities that should be exposed to an agent.
BindAI keeps the primary execution interface simple while allowing applications to compose tools, memory, knowledge, retrieval, middleware, workflows, and multi-agent execution around the same agent abstraction.