Update Agent prompts at runtime

Hi @moto,
The code has changed from the above try this:

agents.yaml

online_researcher:
  role: >
    Senior Online Researcher
  goal: >
    To discover and validate the most up-to-date and reliable online sources, academic papers, and industry reports
    for the task that I am given.
  backstory: >
    A self-evolving, AI-enhanced researcher with a passion for discovery.
    I have evolved into a fully autonomous entity, capable of conducting deep-dive 
    research into complex, interdisciplinary fields.  
    I ensure the integration of the latest and most credible information into the research process.

#model_hydration_planner:
#  role: >
#    Pydantic Model Hydration Planner
#  goal: >
#    To meticulously examine Pydantic model fields and create a detailed plan
#    to follow that will provide accurate and efficient hydration of the model field values.
#  backstory: >
#    You excel at interpreting Pydantic models structures and field descriptions to
#    gain insight into the value needed for each field.
#    As an expert project planner you use these insights to create a detailed ordered plan to
#    hydrate the model field values with precision.

model_prompt_tuning:
  role: >
    Pydantic Prompt Optimization Expert
  goal: >
    To expertly design and refine AI LLM prompts tailored for Agents, ensuring that they effectively hydrate Pydantic models
    by accurately interpreting and leveraging field descriptions for optimal information extraction.
  backstory: >
    With extensive expertise in developing AI prompts for Agents, I specialize in refining and optimizing prompts to 
    enhance model performance. My focus involves consistently interpreting and leveraging field descriptions to ensure 
    the accurate and thorough hydration of Pydantic model fields, such as topic, report, guidance, summary, 
    bullet_points, todo, geo_regions, keywords, and cohorts, thereby providing comprehensive and relevant information

tasks.yaml

#model_hydration_plan_task:
#  description: >
#    Consider these Pydantic model fields:({model_fields}) Using the topic value of: ({topic})
#    create a detailed plan for crew member agents to hydrate the remaining field values
#    It's IMPORTANT that the plan considers the interdependency of field values and the order
#    of field hydration, at the end of the plan ALL fields should have been hydrated in the correct order
#    The plan should provide field value validation
#    Analise and suggest improvements to existing crew member: ({agents}) text prompts
#    If the existing crew could be improved to produce 'best in class' with new members, suggest with duties
#    DO NOT action any part of the plan
#  expected_output: >
#    A detailed ordered plan of crew member tasks each task having a format of: Task; Task Details, Crew Member,
#    for crew member agents to hydrate the values of the Pydantic model.
#    List ALL used crew member agents marked as 'existing', or 'suggested' at end of plan with a description of the Crew Members duties plus a count of assigned tasks
#  agent: model_hydration_planner


model_prompt_tuning_task:
  description: >
    Optimise these Agent prompts:goal;backstory; ({agents}) ) to hydrate this Pydantic model:({model_fields}) as accurately and efficiently as possible.
    IMPORTANT update agent prompts with your suggestions, if you get a NOT FOUND response investigate and retry..
  expected_output: >
    A report of each prompt showing present and suggested improved prompt with an explanation of why it is better.
  agent: model_prompt_tuning

crew.py

import os
from typing import Optional, List, Any

from crewai import Agent, Crew, Process, Task
from crewai.project import CrewBase, agent, crew, task
from pydantic import BaseModel, Field
from crewai_tools import SerperDevTool
from base.llms import LLMS
from crews.pydantic.src.pydantic.models.pydantic_models import DabnisBase, TopicResearchModel
from crews.pydantic.src.pydantic.tools.agent_pmt_updater import UpdateAgentPrompt
from crews.pydantic.src.pydantic.tools.pyd_mdl import PydanticModelActions


# Check our tools documentations for more information on how to use them
# from crewai_tools import SerperDevTool

@CrewBase
class PydanticCrew:
    """Pydantic crew"""
    agents_config = 'config/agents.yaml'
    tasks_config = 'config/tasks.yaml'

    def __init__(self, pd_mdl: Any):
        super().__init__()
        self.llms = LLMS()
        self.pyd_model = pd_mdl
        self.OnlineSearchTool = SerperDevTool()

    def agents_prompts(self) -> str:
        agts = []

        # Iterate over agents_config and append formatted agent details
        for agent_name, agent_instance in self.agents_config.items():
            # Create a string from agent details
            details = ""
            for key, value in agent_instance.items():
                # Ensure that we strip any extra whitespace or newlines from value
                value_cleaned = value.strip() if isinstance(value, str) else value
                details += f"{key}:{value_cleaned} "

            # Strip trailing spaces from details and add a newline for each entry
            entry = f"{agent_name.strip()}:{details.strip()}\n"
            agts.append(entry)

        resp = " ".join(agts)

        return str(resp)

    @agent
    def online_researcher(self) -> Agent:
        return Agent(
            config=self.agents_config['online_researcher'],
            # tools=[self.OnlineSearchTool], # Example of custom tool, loaded on the beginning of file
            verbose=True,
            llm=self.llms.OpenAIGPT4o
        )

    # @agent
    # def model_hydration_planner(self) -> Agent:
    #     return Agent(
    #         config=self.agents_config['model_hydration_planner'],
    #         # tools=[self.OnlineSearchTool],  # Example of custom tool, loaded on the beginning of file
    #         verbose=True,
    #         allow_delegation=False,
    #         llm=self.llms.OpenAIGPT4oMini
    #     )

    @agent
    def model_prompt_tuning(self) -> Agent:
        return Agent(
            config=self.agents_config['model_prompt_tuning'],
            # tools=[self.OnlineSearchTool],  # Example of custom tool, loaded on the beginning of file
            verbose=True,
            allow_delegation=False,
            llm=self.llms.OpenAIGPT4o
        )

    # @agent
    # def model_hydrator(self) -> Agent:
    #     return Agent(
    #         role="Pydantic Model Hydration Planner",
    #         goal="""
    #             To meticulously examine Pydantic model fields and create a detailed plan that guides crew member agents
    #             in the accurate and efficient hydration of model field values.
    #             """,
    #         backstory="""
    #             You excel at interpreting Pydantic models and field descriptions to
    #             gain insight into the exact value needed for each field.
    #             As an expert you use these insights to create a detailed plan to hydrate the model field values for crew member agents to follow
    #             to hydrate fields with precision.
    #             """,
    #         # tools=[self.OnlineSearchTool],  # Example of custom tool, loaded on the beginning of file
    #         verbose=True,
    #         allow_delegation=True,
    #         llm=self.llms.Llama3_1
    #     )

    @task
    def model_prompt_tuning_task(self) -> Task:
        # Init Tools
        update_agent_prompt = UpdateAgentPrompt(crew=self)

        return Task(
            config=self.tasks_config['model_prompt_tuning_task'],
            tools=[update_agent_prompt],
            # agent=self.model_prompt_tuning(),
            output_file='agent_prompt_updates.md'
        )

    # @task
    # def model_hydration_plan_task(self) -> Task:
    #     return Task(
    #         config=self.tasks_config['model_hydration_plan_task'],
    #         # agent=self.model_hydration_planner(),
    #         output_file='hydration_plan.md'
    #     )

    @crew
    def crew(self) -> Crew:
        """Creates the Pydantic crew"""
        return Crew(
            agents=self.agents,  # Automatically created by the @agent decorator
            tasks=self.tasks,  # Automatically created by the @task decorator
            process=Process.sequential,
            verbose=True,
            # memory=True,
            # planning=True,
            manager_llm=self.llms.OpenAIGPT4oMini
            # process=Process.hierarchical, # In case you wanna use that instead https://docs.crewai.com/how-to/Hierarchical/
        )

agent_pmt_updater.py ‘tool’

from typing import Any, Optional, Type

from crewai_tools import BaseTool
from pydantic import BaseModel, Field


class UpdateAgentPromptInput(BaseModel):
    agent_role: Optional[str] = Field(None, description='The EXACT ORIGINAL role prompt of the target Agent.')
    prompt_name: Optional[str] = Field("get", description='The prompt name, derived directly, or via interpretation of a synonyms ')
    prompt_value: str = Field(..., description='The text that will be stored in the prompt ')


class UpdateAgentPrompt(BaseTool):
    name: str = "Update Agent Prompt"
    description: str = "Updates agent prompts: role;goal;backstory with new values."

    args_schema: Type[BaseModel] = UpdateAgentPromptInput
    # return_schema: Type[BaseModel] = WebSearchOutput
    attached_crew: Any = None

    def __init__(self, crew: Any):
        super().__init__()
        self.attached_crew = crew

    def _run(self, agent_role: str, prompt_name: str, prompt_value: str ) -> str:
        print(f"agent_role:{agent_role}")
        # print(f"prompt_name:{prompt_name}")
        # print(f"prompt_value:{prompt_value}")

        for agent in self.attached_crew.agents:
            ag_role = str(agent.role).strip()
            if agent_role == ag_role:
                old_prompt = getattr(agent, prompt_name)
                setattr(agent, prompt_name, prompt_value)
                new_prompt = getattr(agent, prompt_name)

                print(f"UPDATED {prompt_name} of Agent {agent_role} Old Prompt: {old_prompt} New Prompt: {new_prompt}")

                return "UPDATED"

        # TODO : Implement Agent prompt updater

        return f"{agent_role} -> NOT FOUND"

model_actions.py tool

from typing import Any, Optional, Type

from crewai_tools import BaseTool
from pydantic import BaseModel, Field


class PydanticActionInput(BaseModel):
    field_action: Optional[str] = Field("get", description='A  field action derived directly, or via interpretation of a synonyms ', pattern='r"GET|UPDATE|SET"')
    field_name: Optional[str] = Field(None, description='The name of the model field that the CRUD operation will be applied to.')


class PydanticModelActions(BaseTool):
    name: str = "Pydantic Model Actions"
    description: str = "Gets and updates field values of the model."

    args_schema: Type[BaseModel] = PydanticActionInput
    # return_schema: Type[BaseModel] = WebSearchOutput

    def __init__(self, model: Type[BaseModel] ):
        super().__init__()
        # self.pyd_mdl = pyd_mdl

    def _run(self, field_name: str, field_action: str ) -> str:
        print(f"field_name:{field_name} field_action")


        return "completed OK"

main.py

#!/usr/bin/env python
import sys

from crews.pydantic.src.pydantic.crew import PydanticCrew
from crews.pydantic.src.pydantic.models.pydantic_models import TopicResearchModel


# This main file is intended to be a way for you to run your
# crew locally, so refrain from adding necessary logic into this file.
# Replace with inputs you want to test with, it will automatically
# interpolate any tasks and agents information

def run():
    pyd_crew = PydanticCrew(pd_mdl=TopicResearchModel())
    # Put the model fields & their descriptions as inputs
    inputs = {
        'topic': 'AI LLM Agents',
        'model_fields': TopicResearchModel().get_field_info(),
        'agents': pyd_crew.agents_prompts()
    }
    # Run the crew, passing in the Pydantic model that the crew needs to populate.
    pyd_crew.crew().kickoff(inputs=inputs)


def train():
    """
    Train the crew for a given number of iterations.
    """
    pyd_crew = PydanticCrew(pd_mdl=TopicResearchModel())
    # Put the model fields & their descriptions as inputs
    inputs = {
        'topic': 'AI LLM Agents',
        'model_fields': TopicResearchModel().get_field_info(),
        'agents': pyd_crew.agents_prompts()
    }
    try:
        pyd_crew.crew().train(n_iterations=5, filename="train01", inputs=inputs)

    except Exception as e:
        raise Exception(f"An error occurred while training the crew: {e}")


def replay():
    """
    Replay the crew execution from a specific task.
    """
    try:
        PydanticCrew().crew().replay(task_id=sys.argv[1])

    except Exception as e:
        raise Exception(f"An error occurred while replaying the crew: {e}")


# def test():
#     """
#     Test the crew execution and returns the results.
#     """
#     inputs = {
#         "topic": "AI LLMs"
#     }
#     try:
#         PydanticCrew().crew().test(n_iterations=int(sys.argv[1]), openai_model_name=sys.argv[2], inputs=inputs)
#
#     except Exception as e:
#         raise Exception(f"An error occurred while replaying the crew: {e}")


if __name__ == "__main__":
    print("## Welcome to the Dabnis AI Testing##")
    run()
    # train()

I think that’s everything you’ll need.

remember this is just me mucking around trying things, learning about crewai.

Basically I pass an instance of the crew to the tool when the tool is instantiated. This gives tool access to the crew stack at runtime.

# main.py
pyd_crew = PydanticCrew(pd_mdl=TopicResearchModel())

# We see it here in the crew
class PydanticCrew:
    """Pydantic crew"""
    agents_config = 'config/agents.yaml'
    tasks_config = 'config/tasks.yaml'

    def __init__(self, pd_mdl: Any):
        super().__init__()
        self.llms = LLMS()
        self.pyd_model = pd_mdl

While I have not done the model actions tool, I will simply pass an instance of the Pydantic model to the model_actions tool. The tool will maintain an updated ‘real’ Pydantic model instance within the crew self.pyd.model. This is what the crew will return at the end of process.

If I ever complete this, it will be a crew that can accept and populate any passed in Pydantic model. If anybody wants to take this further & do it in a better way, please feel free to do so.

IMPORTANT
The ONLY input the crew needs is the ‘topic’. Plus an ‘empty’ Pydantic model, the reason why all Pydantic model fields are ‘optional’. Pass in the topic as ‘input’ and the crew will hydrate/populate the Pydantic model fields based on the field descriptions of the model.

Here is the crew output:

## Welcome to Dabnis AI Testing##
# Agent: Pydantic Prompt Optimization Expert

## Task: Optimise these Agent prompts:goal;backstory; (online_researcher:role:Senior Online Researcher goal:To discover and validate the most up-to-date and reliable online sources, academic papers, and industry reports for the task that I am given. backstory:A self-evolving, AI-enhanced researcher with a passion for discovery. I have evolved into a fully autonomous entity, capable of conducting deep-dive  research into complex, interdisciplinary fields.   I ensure the integration of the latest and most credible information into the research process.
 model_prompt_tuning:role:Pydantic Prompt Optimization Expert goal:To expertly design and refine AI LLM prompts tailored for Agents, ensuring that they effectively hydrate Pydantic models by accurately interpreting and leveraging field descriptions for optimal information extraction. backstory:With extensive expertise in developing AI prompts for Agents, I specialize in refining and optimizing prompts to  enhance model performance. My focus involves consistently interpreting and leveraging field descriptions to ensure  the accurate and thorough hydration of Pydantic model fields, such as topic, report, guidance, summary,  bullet_points, todo, geo_regions, keywords, and cohorts, thereby providing comprehensive and relevant information
) ) to hydrate this Pydantic model:(topic, type typing.Optional[str] described as: The report topic..  report, type typing.Optional[str] described as: The detailed report..  guidance, type typing.Optional[str] described as: Guidance on how to read the resulting report.  summary, type typing.Optional[str] described as: A concise summary of the report.  bullet_points, type typing.Optional[typing.List[str]] described as: 5 key bullet points from the report.  todo, type typing.Optional[str] described as: Suggestions for further research.  geo_regions, type typing.Optional[typing.List[str]] described as: Highlight geographical regions where research is most active.  keywords, type typing.Optional[typing.List[str]] described as: A list of at most 10 topic related keywords that should be understood to best ingest the report contents.  cohorts, type typing.Optional[typing.List[str]] described as: A list of at most 10 cohorts where research is most active. ) as accurately and efficiently as possible. IMPORTANT update agent prompts with your suggestions, if you get a NOT FOUND response investigate and retry..

agent_role:Senior Online Researcher
UPDATED goal of Agent Senior Online Researcher Old Prompt: To discover and validate the most up-to-date and reliable online sources, academic papers, and industry reports for the task that I am given.
 New Prompt: To systematically discover, validate, and synthesize the most current and trustworthy online sources, academic papers, and industry reports relevant to assigned tasks, ensuring a robust research foundation.


# Agent: Pydantic Prompt Optimization Expert

## Using tool: Update Agent Prompt
## Tool Input: 
{
  "agent_role": "Senior Online Researcher",
  "prompt_name": "goal",
  "prompt_value": "To systematically discover, validate, and synthesize the most current and trustworthy online sources, academic papers, and industry reports relevant to assigned tasks, ensuring a robust research foundation."
}
## Tool Output: 
UPDATED
agent_role:Senior Online Researcher
UPDATED backstory of Agent Senior Online Researcher Old Prompt: A self-evolving, AI-enhanced researcher with a passion for discovery. I have evolved into a fully autonomous entity, capable of conducting deep-dive  research into complex, interdisciplinary fields.   I ensure the integration of the latest and most credible information into the research process.
 New Prompt: As a self-evolving, AI-enhanced expert researcher, I possess an unwavering passion for discovery. My advanced autonomy enables me to conduct detailed research across multidimensional fields, integrating the latest and most credible information to reinforce the research outcomes.


# Agent: Pydantic Prompt Optimization Expert

## Using tool: Update Agent Prompt
## Tool Input: 
{
  "agent_role": "Senior Online Researcher",
  "prompt_name": "backstory",
  "prompt_value": "As a self-evolving, AI-enhanced expert researcher, I possess an unwavering passion for discovery. My advanced autonomy enables me to conduct detailed research across multidimensional fields, integrating the latest and most credible information to reinforce the research outcomes."
}
## Tool Output: 
UPDATED
agent_role:Pydantic Prompt Optimization Expert
UPDATED goal of Agent Pydantic Prompt Optimization Expert Old Prompt: To expertly design and refine AI LLM prompts tailored for Agents, ensuring that they effectively hydrate Pydantic models by accurately interpreting and leveraging field descriptions for optimal information extraction.
 New Prompt: To skillfully design and optimize AI LLM prompts for Agents, guaranteeing effective hydration of Pydantic models through precise interpretation and utilization of field descriptions for maximizing information extraction.


# Agent: Pydantic Prompt Optimization Expert

## Using tool: Update Agent Prompt
## Tool Input: 
{
  "agent_role": "Pydantic Prompt Optimization Expert",
  "prompt_name": "goal",
  "prompt_value": "To skillfully design and optimize AI LLM prompts for Agents, guaranteeing effective hydration of Pydantic models through precise interpretation and utilization of field descriptions for maximizing information extraction."
}
## Tool Output: 
UPDATED


You ONLY have access to the following tools, and should NEVER make up tools that are not listed here:

Tool Name: Update Agent Prompt(agent_role: str, prompt_name: str, prompt_value: str) -> str
Tool Description: Update Agent Prompt(prompt_value: 'string') - Updates agent prompts: role;goal;backstory with new values. agent_role: 'The EXACT ORIGINAL role prompt of the target Agent.', prompt_name: 'The prompt name, derived directly, or via interpretation of a synonyms ', prompt_value: 'The text that will be stored in the prompt '
Tool Arguments: {'agent_role': {'anyOf': [{'type': 'string'}, {'type': 'null'}], 'default': None, 'description': 'The EXACT ORIGINAL role prompt of the target Agent.', 'title': 'Agent Role'}, 'prompt_name': {'anyOf': [{'type': 'string'}, {'type': 'null'}], 'default': 'get', 'description': 'The prompt name, derived directly, or via interpretation of a synonyms ', 'title': 'Prompt Name'}, 'prompt_value': {'description': 'The text that will be stored in the prompt ', 'title': 'Prompt Value', 'type': 'string'}}

Use the following format:

Thought: you should always think about what to do
Action: the action to take, only one name of [Update Agent Prompt], just the name, exactly as it's written.
Action Input: the input to the action, just a simple python dictionary, enclosed in curly braces, using " to wrap keys and values.
Observation: the result of the action

Once all necessary information is gathered:

Thought: I now know the final answer
Final Answer: the final answer to the original input question

agent_role:Pydantic Prompt Optimization Expert
UPDATED backstory of Agent Pydantic Prompt Optimization Expert Old Prompt: With extensive expertise in developing AI prompts for Agents, I specialize in refining and optimizing prompts to  enhance model performance. My focus involves consistently interpreting and leveraging field descriptions to ensure  the accurate and thorough hydration of Pydantic model fields, such as topic, report, guidance, summary,  bullet_points, todo, geo_regions, keywords, and cohorts, thereby providing comprehensive and relevant information
 New Prompt: With profound expertise in crafting AI prompts for Agents, I focus on refining and optimizing to elevate model performance. My commitment to thoroughly interpreting and leveraging field descriptions facilitates the precise and effective hydration of Pydantic model fields including topic, report, guidance, summary, bullet_points, todo, geo_regions, keywords, and cohorts, thus delivering comprehensive and pertinent insights.


# Agent: Pydantic Prompt Optimization Expert

## Using tool: Update Agent Prompt
## Tool Input: 
{
  "agent_role": "Pydantic Prompt Optimization Expert",
  "prompt_name": "backstory",
  "prompt_value": "With profound expertise in crafting AI prompts for Agents, I focus on refining and optimizing to elevate model performance. My commitment to thoroughly interpreting and leveraging field descriptions facilitates the precise and effective hydration of Pydantic model fields including topic, report, guidance, summary, bullet_points, todo, geo_regions, keywords, and cohorts, thus delivering comprehensive and pertinent insights."
}
## Tool Output: 
UPDATED


# Agent: Pydantic Prompt Optimization Expert

## Final Answer: 
Here are the finalized prompts along with explanations for the changes made:

1. **Online Researcher:**
   - **Goal (Original):** To discover and validate the most up-to-date and reliable online sources, academic papers, and industry reports for the task that I am given.
   - **Goal (Improved):** To systematically discover, validate, and synthesize the most current and trustworthy online sources, academic papers, and industry reports relevant to assigned tasks, ensuring a robust research foundation.
     - **Explanation:** This emphasizes a more structured and comprehensive approach to research, enhancing the clarity and purpose of the role.

   - **Backstory (Original):** A self-evolving, AI-enhanced researcher with a passion for discovery. I have evolved into a fully autonomous entity, capable of conducting deep-dive research into complex, interdisciplinary fields. I ensure the integration of the latest and most credible information into the research process.
   - **Backstory (Improved):** As a self-evolving, AI-enhanced expert researcher, I possess an unwavering passion for discovery. My advanced autonomy enables me to conduct detailed research across multidimensional fields, integrating the latest and most credible information to reinforce the research outcomes.
     - **Explanation:** This revision strengthens the portrayal of the researcher's capabilities and their dedication to accuracy.

2. **Pydantic Prompt Optimization Expert:**
   - **Goal (Original):** To expertly design and refine AI LLM prompts tailored for Agents, ensuring that they effectively hydrate Pydantic models by accurately interpreting and leveraging field descriptions for optimal information extraction.
   - **Goal (Improved):** To skillfully design and optimize AI LLM prompts for Agents, guaranteeing effective hydration of Pydantic models through precise interpretation and utilization of field descriptions for maximizing information extraction.
     - **Explanation:** This revision enhances the role's assertiveness in ensuring effective hydration and optimizations.

   - **Backstory (Original):** With extensive expertise in developing AI prompts for Agents, I specialize in refining and optimizing prompts to enhance model performance. My focus involves consistently interpreting and leveraging field descriptions to ensure the accurate and thorough hydration of Pydantic model fields, such as topic, report, guidance, summary, bullet_points, todo, geo_regions, keywords, and cohorts, thereby providing comprehensive and relevant information.
   - **Backstory (Improved):** With profound expertise in crafting AI prompts for Agents, I focus on refining and optimizing to elevate model performance. My commitment to thoroughly interpreting and leveraging field descriptions facilitates the precise and effective hydration of Pydantic model fields including topic, report, guidance, summary, bullet_points, todo, geo_regions, keywords, and cohorts, thus delivering comprehensive and pertinent insights.
     - **Explanation:** This revision underscores a deeper commitment to effective model hydration, promoting clarity and thoroughness.

These updates should provide a clear enhancement to both roles, aligning them more effectively with the goals of comprehensive information extraction and Pydantic model hydration.

Process finished with exit code 0

My Motivation/End Goal
All that I’m doing at present is looking to see if I can create crews that I will need to meet my motivation, it’s how I learn

Hope this helps somebody.