Skip to content

Command

In our platform, the Command implements the Command Pattern, effectively separating workflow orchestration (Nodes) from invoke logic (Tools). Commands encapsulate the request or invoke logic, allowing the orchestrator (Node) to delegate invoke to the executor (Tool) without needing to know the internal details of the invoke process.

Using the Command Pattern brings several significant benefits:

  • Separation of Concerns: Clearly separates orchestration logic from invoke logic, making the system more modular.
  • Flexibility and Extensibility: Allows for easy swapping, extension, and customization of invoke logic without altering workflow structures.
  • Improved Maintainability: Facilitates testing and debugging by isolating command logic within distinct units.

The Command interface class itself primarily defines the interface structure and thus does not contain specific instance fields.

Method Description
invoke Defines synchronous invoke logic to process inputs and return results; must be implemented by subclasses.
a_invoke Defines asynchronous invoke logic supporting streaming or concurrent processes; must be implemented by subclasses.
to_dict Serializes command configurations or state for persistence or debugging purposes; must be implemented by subclasses.

The Command interface class utilizes an inner Builder class to facilitate structured and step-by-step construction of Command instances, enhancing readability and configurability.

Developers implement custom Commands tailored to specific logic or operational needs by inheriting from this base Command class and overriding the required methods. This approach empowers developers to flexibly craft specialized behaviors while maintaining consistency across the workflow invoke environment.

The concrete implementation of Command interface should be with its associated tools. Here are some examples.

LLM Response Command and LLM Stream Command

LLMResponseCommand encapsulates synchronous LLM usage within a command, allowing a node to request the LLM for a response.

Fields:

Field Description
llm An LLM instance (e.g., OpenAI) that provides the response

Key methods are:

Method Description
invoke(invoke_context, input_data) Synchronously obtains a single response from the LLM based on the provided messages.
a_invoke(invoke_context, input_data) Asynchronously streams generated messages from the LLM.
to_dict() Serializes the command’s state, including its associated LLM configuration.

The LLMStreamResponseCommand specializes LLMResponseCommand for stream use cases where synchronous responses must be disabled, and only relies exclusively on asynchronous streaming via a_invoke.

Function Calling Command

FunctionCallCommand is a concrete implementation of the Command interface that allows a Node to call a FunctionCallTool. By assigning a FunctionCallTool to the command, the Node can trigger function invoke without needing to know how arguments are parsed or how the function is actually invoked.

Fields:

Field Description
function_tool A FunctionCallTool instance that encapsulates the registered function and its invoke logic.

Methods:

Method Description
invoke(invoke_context, input_data) Invokes the function_tool's synchronous invoke method, returning a list of resulting Message objects.
a_invoke(invoke_context, input_data) Calls the function_tool's asynchronous a_invoke, yielding one or more Message objects in an async generator.
get_function_specs() Retrieves the function specifications (schema, name, parameters) from the underlying function_tool.
to_dict() Serializes the command’s current state, including the function_tool configuration.

By passing a FunctionCallTool to the function_tool field, you can seamlessly integrate function-based logic into a Node’s orchestration without embedding invoke details in the Node or the tool consumer. This separation keeps workflows flexible and easy to extend.

Embedding Response Command and RAG Response Command

EmbeddingResponseCommand encapsulates a RetrievalTool for transforming input messages into embeddings, retrieving relevant content, and returning it as a Message. This command is used by EmbeddingRetrievalNode.

EmbeddingResponseCommand fields:

Field Description
retrieval_tool A RetrievalTool instance for embedding-based lookups, returning relevant data

EmbeddingResponseCommand methods:

Method Description
invoke(invoke_context, input_data) Synchronously calls retrieval_tool.invoke, returning the resulting Message.
a_invoke(invoke_context, input_data) Asynchronously calls retrieval_tool.a_invoke, yielding one or more Message objects.
to_dict() Serializes the command’s state, including the retrieval_tool configuration.

RagResponseCommand similarly delegates to a RagTool that performs retrieval-augmented generation. This command is used by RagNode.

RagResponseCommand fields:

Field Description
rag_tool A RagTool instance for retrieval-augmented generation.

RagResponseCommand methods:

Method Description
invoke(invoke_context, input_data) Synchronously calls rag_tool.invoke, returning a Message with retrieval results.
a_invoke(invoke_context, input_data) Asynchronously invokes rag_tool.a_invoke, yielding partial or complete messages from the retrieval-augmented flow.
to_dict() Serializes the command’s state, reflecting the assigned RagTool configuration.

Both commands enable a node to delegate specialized retrieval operations to their respective tools, without needing to manage the internal logic of how embeddings or RAG processes are performed.

Function Command

FunctionCommand is a concrete implementation of the Command interface that allows a Node to invoke general function-based operations through a FunctionTool. This command provides a flexible framework for integrating custom function logic into event-driven workflows, enabling nodes to perform various computational tasks without embedding invoke details directly in the node logic.

FunctionCommand fields:

Field Description
function_tool A FunctionTool instance that encapsulates the function invoke logic.

FunctionCommand methods:

Method Description
invoke(invoke_context, input_data) Synchronously calls function_tool.invoke, returning the resulting Message.
a_invoke(invoke_context, input_data) Asynchronously calls function_tool.a_invoke, yielding one or more Message objects.
to_dict() Serializes the command's state, including the function_tool configuration.

The FunctionCommand enables nodes to delegate function-based operations to their respective tools, maintaining clean separation between workflow orchestration and function invoke logic. This design allows for easy integration of various computational tasks while keeping the system modular and extensible.