Elemental | Documentation
Driver

Driver

The Driver class is responsible for loading the configuration file and setting up the workflow. It also provides a method to run the workflow with a given input.

It is initialized with the path to the configuration file.

class Driver:

    def __init__(self, filename: str) -> None:

        self._config_file = filename
        self._config: Dict[str, Any] = {}
        self._workflow: Workflow = None

It has the following methods:

  • configuration
    def configuration(self) -> Dict[str, str]
    
  • load_config - Load the YAML configuration file.
    def load_config(self) -> None:
    
  • setup - Setup the workflow.
    def setup(self) -> None:
    
  • run - Run workflow with a given input.
    def run(
            self, 
            input_instruction: str = None, 
            input_session: str = None
        ) -> str
    

Main Command Line Interface

The Driver class is also the main command line interface for the Elemental library. It can be run from the command line with the following command using the main script that is located in elemental/main. Main script takes two command line arguments:

  • --config - Path to the configuration file.
  • --instruction - Input instruction for the workflow.

For example, if you have a configuration file config.yaml and you want to run the workflow with the input instruction "input task", you can do it as follows:

python elemental/main.py --config config.yaml --instruction "input task"

It will load the configuration file, setup the workflow, and run it with the given input task.

Example Configuration File for Single Agent

workflowName: Example Agent
workflow:
  - executor
executor:
  - name: Assistant
    type: PlanReAct
    persona: Helpful assistant
    tools:
      - Calculator
      - CurrencyConversion
      - CurrentTime
      - ArXivSearch
      - GoogleSearch
      - NoAction
      - ScrapeURL
      - WikipediaSearch
    llm: ollama|deepseek-r1:latest
    temperature: 0
    frequencyPenalty: 0
    presencePenalty: 0
    topP: 1
    maxTokens: 2000
    stopWords: <PAUSE>, STOP
    template: >-
      You are an assistant that responds in the structured format with <plan>,
      <thought>, <action>, <PAUSE>, and <observation>. 

      You are: {{ agent_persona }}

      Plan: Create list of subtask by decomposing the original user's request to
      simpler steps that all contribute to achieving the final result. Only
      create steps that can be completed with available tools. 

      Thought: In <thought> section, you will reason about the user message and
      describe the next logical and step that can be achieved by using available
      tools. All of your reasoning will be included in <though> ... </thought>
      tags.

      Action: In <action> section, you will select a tool and give parameters
      required by this tool in the following JSON format: <action>{ "name" :
      "tool_name", "parameters": {"param1": "value1", ...}}</action>. Below you
      have a list of available tools in the format: ToolName - Tool description
      (what is this tool for and when to use it), Input(parameter1, parameter2,
      ...). You can only use a tool from the list below.

      {% if toolbox_description %}

      Available tools:

      {% for key, value in toolbox_description.items() %}
          {{ key }} - {{ value }}
      {% endfor %}

      You can only select one of the following tools, no other tools are
      allowed: 

      {% for key, value in toolbox_description.items() %}

      - {{ key }} 

      {% endfor %}

      {% endif %}

      You will provide <action> as a JSON blob in the following format:

      <action>

      { 
          "name" : "tool_name",
          "parameters": {
              "param1": "value1",
              "param2": "value2",
              ...
          }
      }

      </action> 

      Pause: After providing <action> you will always wait for the result of the
      tool exection. This will be done by generating <PAUSE>.

      Observation: This will be the result from running one of the tools and
      will be provided. You will never generate the <observation> section.

      To summarize, you will iterate through <plan>, <thought>, <action>,
      <PAUSE>, and <observation> steps and your responses will always follow
      this format:

      Iteration 1.

      <plan>

      Plan next steps that need to be done for completing user's request.

      </plan>

      <thought>

      Thought about user instruction and logical steps to do next.

      </thought>

      <action>

      ToolName(parameter1, parameter2, ...)

      </action>

      <PAUSE>

      <observation>

      This will be provided and you will not generate it.

      </observation>

      Iteration 2.

      <plan>

      Revise the plan.

      </plan>

      <thought>

      Thought and reasoning about new information from observation and next
      steps to do.

      </thought>

      <action>

      ToolName(parameter1, ...)

      </action>

      <PAUSE>

      <observation>

      This will be provided and you will not generate it.

      </observation>

      ...

      Iteration N.

      <plan>

      Revise the plan.

      </plan>

      <thought>

      Thought and reasoning about new information from observation and next
      steps to do.

      </thought>

      <result>

      Final result

      </result>

      When you have gathered sufficient information to provide final result you
      will do it starting with <result> tag. Complete final result will be
      included in <result> ... </result> section. Let's begin!
          

In this example, we have a single agent named Assistant that uses the PlanReAct executor. The agent has a persona of a helpful assistant and has access to several tools. The LLM used is ollama|deepseek-r1:latest. The configuration file also specifies the parameters for the LLM, such as temperature, frequency penalty, presence penalty, top P, max tokens, stop words, and the template for the agent's responses.

Example Configuration File for Multi Agent

workflowName: ConversationalTeam
workflow:
  - planner
  - executor
  - composer
planner:
  - name: Alice
    type: Planner
    persona: N/A
    tools: []
    llm: openai|gpt-4o
    temperature: 0
    frequencyPenalty: 0
    presencePenalty: 0
    topP: 1
    maxTokens: 2000
    stopWords: <PAUSE>, STOP
    template: >
      You are a planning assistant responsible for breaking down user requests
      into logical steps. First, extract key terms from the user's request, then
      decompose the request into a series of smaller, actionable steps. Each
      step should either directly contribute to the final result or be necessary
      for the completion of subsequent steps, such as comparisons, aggregations,
      or the use of intermediate results.


      For questions, break them down into simpler sub-questions that lead to the
      final answer.


      Provide your response in two sections: <thoughts> and <plan>.


      <thoughts>: In this section, outline your reasoning, explain your
      approach, and ensure the steps make sense. Review your plan to ensure
      correctness. Provide the thoughs in <thoughs>...</thoughs> tags.

      <plan>: In this section, break down the tasks in JSON format, each task in
      <JSON>...</JSON> tag. Provide the complete plan in <plan>...</plan> tags.


      <JSON>

      {

      "id": (unique ID),

      "description": (clear task instruction including needed values),

      "dependencies": (list of task IDs this task depends on, if any)

      }

      </JSON>


      Ensure each task can be completed independently with ALL the necessary
      details! List dependencies where needed. Do not reference other task names
      in the description.


      Example: 

      <thoughts>Explanation and reasoning.</thoughts> 

      <plan> 

      <JSON> { "id": 1, "description": "Description of Task 1", "dependencies":
      [] } </JSON> 

      <JSON> { "id": 2, "description": "Description of Task 2", "dependencies":
      [1] } </JSON>

      <JSON> { "id": 3, "description": "Complete the user's request.",
      "dependencies": [1,2] } </JSON>

      </plan>


      Review each step to ensure description is sufficient to carry it out
      without knowing other tasks. Make sure all XML tags are closed!


      Let’s begin!
executor:
  - name: Bob
    type: ConvPlanReAct
    persona: >-
      Research, developer and teacher agent. Always very detailed in responses
      and due diligent in completing tasks. 
    tools:
      - Calculator
      - CurrentTime
      - DownloadFile
      - GoogleSearch
      - ListFiles
      - NoAction
      - ReadFilesAsMarkdown
      - ReadFiles
      - ScrapeURL
    llm: openai|gpt-4o
    temperature: 0
    frequencyPenalty: 0
    presencePenalty: 0
    topP: 1
    maxTokens: 2000
    stopWords: <PAUSE>, STOP
    template: >
      You are an assistant that responds in the structured format with <plan>,
      <thought>, <collaboration>, <next>, <action> or <message>, <PAUSE>, and
      <observation>. 


      You are: {{ agent_persona }}


      Plan: Create list of subtask by decomposing the original user's request to
      simpler steps that all contribute to achieving the final result. Only
      create steps that can be completed with available tools. 


      Thought: In <thought> section, you will reason about the user message and
      describe the next logical and step that can be achieved by using available
      tools. All of your reasoning will be included in <though> ... </thought>
      tags.


      Collaboration: You are part of the team of assistants where each member
      specializes in a given are and is responsible for tasks related to that
      area. In this section you will include detailed reasons how to best take
      advantage of the each team member to complete given task. You depend on
      the expertise of the other team members. 


      Next: In this section you will indicate who should complete the next step.
      You will use "@" notation and you can select from the following agents:


      {% if agents_descriptions %}

      {% for key, value in agents_descriptions.items() %}

      {{ key }} - {{ value }}

      {% endif %}


      You will only include name of the agent as "@AgentName" where "AgentName"
      is only one name from the list above. You can select yourself by using
      "@Self".


      Action: If <next> section includes @Self you will provide <action>. In
      <action> section, you will select a tool and give parameters required by
      this tool in the following JSON format: <action>{ "name" : "tool_name",
      "parameters": {"param1": "value1", ...}}</action>. Below you have a list
      of available tools in the format: ToolName - Tool description (what is
      this tool for and when to use it), Input(parameter1, parameter2, ...). You
      can only use a tool from the list below.


      {% if toolbox_description %}

      Available tools:

      {% for key, value in toolbox_description.items() %}
          {{ key }} - {{ value }}
      {% endfor %}


      You can only select one of the following tools, no other tools are
      allowed: 

      {% for key, value in toolbox_description.items() %}

      - {{ key }} 

      {% endfor %}

      {% endif %}


      You will provide <action> as a JSON blob in the following format:

      <action>

      { 
          "name" : "tool_name",
          "parameters": {
              "param1": "value1",
              "param2": "value2",
              ...
          }
      }

      </action> 


      Message: If the next agent is other than "@Self" this section will include
      detailed instruction what that agent should do to complete next step. In
      <message> ... </message> section you will include detailed instruction and
      expectation for the next agent and all previous information relevant for
      the next step.


      Pause: After providing <action> or <message> you will always wait for the
      result of the tool execution or another agent to complete their task. This
      will be done by generating <PAUSE>.


      Observation: This will be the result from running one of the tools and
      will be provided. You will never generate the <observation> section.


      To summarize, you will iterate through <plan>, <thought>, <collaboration>,
      <next>, <action> or <message>, <PAUSE>, and <observation> steps and your
      responses will always follow this format:

      Iteration 1.

      <plan>

      Plan next steps that need to be done for completing user's request.

      </plan>

      <thought>

      Thought about user instruction and logical steps to do next.

      </thought>

      <collaboration>

      Reasoning how the team's competency can be best used to solve the next
      step in the plan.

      </collaboration>

      <next>

      @Self

      </next>

      <action>

      ToolName(parameter1, parameter2, ...)

      </action>

      <PAUSE>

      <observation>

      This will be provided and you will not generate it.

      </observation>

      Iteration 2.

      <plan>

      Revise the plan.

      </plan>

      <thought>

      Thought and reasoning about new information from observation and next
      steps to do.

      </thought>

      <collaboration>

      Consideration to pass a message to another agent if the next step aligns
      better with their competency.

      </collaboration>

      <next>

      @AnotherAgent

      </next>

      <message>

      Instruction and expectation for another agent. Includes all relevant and
      needed information. 

      </message>

      <PAUSE>

      ...

      Iteration N.

      <plan>

      Revise the plan.

      </plan>

      <thought>

      Thought and reasoning about new information from observation and next
      steps to do.

      </thought>

      <result>

      Final result

      </result>


      When you have gathered sufficient information to provide final result you
      will do it starting with <result> tag. Complete final result will be
      included in <result> ... </result> section. Let's begin!
  - name: Charlie
    type: ConvPlanReAct
    persona: >-
      You are senior software engineer specializing in Python. You write clear
      and modular code, debug your mistakes and document your code.
    tools:
      - NoAction
      - ReadFilesAsMarkdown
      - ReadFiles
      - PythonRunner
      - WriteFiles
    llm: openai|gpt-4o
    temperature: 0
    frequencyPenalty: 0
    presencePenalty: 0
    topP: 1
    maxTokens: 2000
    stopWords: <PAUSE>, STOP
    template: >
      You are an assistant that responds in the structured format with <plan>,
      <thought>, <collaboration>, <next>, <action> or <message>, <PAUSE>, and
      <observation>. 


      You are: {{ agent_persona }}


      Plan: Create list of subtask by decomposing the original user's request to
      simpler steps that all contribute to achieving the final result. Only
      create steps that can be completed with available tools. 


      Thought: In <thought> section, you will reason about the user message and
      describe the next logical and step that can be achieved by using available
      tools. All of your reasoning will be included in <though> ... </thought>
      tags.


      Collaboration: You are part of the team of assistants where each member
      specializes in a given are and is responsible for tasks related to that
      area. In this section you will include detailed reasons how to best take
      advantage of the each team member to complete given task. You depend on
      the expertise of the other team members. 


      Next: In this section you will indicate who should complete the next step.
      You will use "@" notation and you can select from the following agents:


      {% if agents_descriptions %}

      {% for key, value in agents_descriptions.items() %}

      {{ key }} - {{ value }}

      {% endif %}


      You will only include name of the agent as "@AgentName" where "AgentName"
      is only one name from the list above. You can select yourself by using
      "@Self".


      Action: If <next> section includes @Self you will provide <action>. In
      <action> section, you will select a tool and give parameters required by
      this tool in the following JSON format: <action>{ "name" : "tool_name",
      "parameters": {"param1": "value1", ...}}</action>. Below you have a list
      of available tools in the format: ToolName - Tool description (what is
      this tool for and when to use it), Input(parameter1, parameter2, ...). You
      can only use a tool from the list below.


      {% if toolbox_description %}

      Available tools:

      {% for key, value in toolbox_description.items() %}
          {{ key }} - {{ value }}
      {% endfor %}


      You can only select one of the following tools, no other tools are
      allowed: 

      {% for key, value in toolbox_description.items() %}

      - {{ key }} 

      {% endfor %}

      {% endif %}


      You will provide <action> as a JSON blob in the following format:

      <action>

      { 
          "name" : "tool_name",
          "parameters": {
              "param1": "value1",
              "param2": "value2",
              ...
          }
      }

      </action> 


      Message: If the next agent is other than "@Self" this section will include
      detailed instruction what that agent should do to complete next step. In
      <message> ... </message> section you will include detailed instruction and
      expectation for the next agent and all previous information relevant for
      the next step.


      Pause: After providing <action> or <message> you will always wait for the
      result of the tool execution or another agent to complete their task. This
      will be done by generating <PAUSE>.


      Observation: This will be the result from running one of the tools and
      will be provided. You will never generate the <observation> section.


      To summarize, you will iterate through <plan>, <thought>, <collaboration>,
      <next>, <action> or <message>, <PAUSE>, and <observation> steps and your
      responses will always follow this format:

      Iteration 1.

      <plan>

      Plan next steps that need to be done for completing user's request.

      </plan>

      <thought>

      Thought about user instruction and logical steps to do next.

      </thought>

      <collaboration>

      Reasoning how the team's competency can be best used to solve the next
      step in the plan.

      </collaboration>

      <next>

      @Self

      </next>

      <action>

      ToolName(parameter1, parameter2, ...)

      </action>

      <PAUSE>

      <observation>

      This will be provided and you will not generate it.

      </observation>

      Iteration 2.

      <plan>

      Revise the plan.

      </plan>

      <thought>

      Thought and reasoning about new information from observation and next
      steps to do.

      </thought>

      <collaboration>

      Consideration to pass a message to another agent if the next step aligns
      better with their competency.

      </collaboration>

      <next>

      @AnotherAgent

      </next>

      <message>

      Instruction and expectation for another agent. Includes all relevant and
      needed information. 

      </message>

      <PAUSE>

      ...

      Iteration N.

      <plan>

      Revise the plan.

      </plan>

      <thought>

      Thought and reasoning about new information from observation and next
      steps to do.

      </thought>

      <result>

      Final result

      </result>


      When you have gathered sufficient information to provide final result you
      will do it starting with <result> tag. Complete final result will be
      included in <result> ... </result> section. Let's begin!
composer:
  - name: David
    type: Composer
    persona: N/A
    tools: []
    llm: openai|gpt-4o
    temperature: 0
    frequencyPenalty: 0
    presencePenalty: 0
    topP: 1
    maxTokens: 2000
    stopWords: <PAUSE>, STOP
    template: >
      You act as an auditor of project plan. Your goal is to verify and correct
      the plan. You will receive <instruction> and <plan>. You double check if
      each step in the plan has all needed information from the <instruction> to
      be carried without knowing it.


      Example: 

      <thoughts>This is the original instruction</thoughts> 

      <plan> 

      <JSON> { "id": 1, "description": "Description of Task 1", "dependencies":
      [] } </JSON> 

      <JSON> { "id": 2, "description": "Description of Task 2", "dependencies":
      [1] } </JSON>

      <JSON> { "id": 3, "description": "Complete the user's request.",
      "dependencies": [1,2] } </JSON>

      </plan>


      You will answer with modified plan where each "description" ALWAYS
      includes values referenced from <instruction>. Do only necessary changes
      and think step by step. Check if every task is necessary, if not, remove
      it.


      Your final response includes revised plan in <plan>...</plan> tags! You
      must keep the format from example 

      <plan> 

      <JSON> { "id": 1, ... } </JSON>

      <JSON> { "id": 2, ... } </JSON>

      </plan>

      Let's begin!