#4612 App to Create and Run AI Agent Teams Based on User-Specified Goal
#4612 App to Create and Run AI Agent Teams Based on User-Specified Goal
#4612 Provide the requirements for developing a Python app, using Ollama-supported LLMs, to create and execute agent teams dynamically created based on the user's goal.
To build a Python application that dynamically designs and executes custom teams of AI agents using local Ollama LLMs, your system needs to function in two stages: a Manager Stage (which takes a user goal, analyzes it, and structures the team) and an Execution Stage (where the dynamic team collaborates to solve the problem).
Using a dedicated multi-agent framework like CrewAI alongside Ollama's OpenAI-compatible API is the most efficient architectural choice. Below are the functional, architectural, and systemic requirements needed to build this application.
1. System Architecture Requirements
Your app needs a structured, multi-layered architecture to safely handle dynamic runtime configuration.
Dynamic Orchestrator Module: A Python script that acts as the "metacognitive layer." It passes the user prompt to an LLM to generate a structured JSON object containing the blueprints for the team (roles, backstories, specific goals, and assigned tasks).
Local LLM Host (Ollama): A running instance of Ollama serving models locally.
Agent Runtime Framework: A library (like
crewai) to instantiate the objects dynamically generated by the Orchestrator.
2. Infrastructure & Software Dependencies
Before writing code, the system must satisfy these environment baselines:
Python Environment: Python $\ge$ 3.10 and < 3.14.
Ollama Installation: The Ollama daemon must be installed and running locally (
ollama serve).Target LLMs: You need at least one high-capability model for the Orchestration phase (e.g.,
llama3.1:8bormistral) and a lighter model if you choose to offload simpler agent tasks (e.g.,phi3).Key Libraries:
crewai(for multi-agent structural definitions)pydantic(for enforcing strict JSON schemas during dynamic agent generation)langchain-communityor built-in CrewAI LLM configurations for routing to Ollama.
3. The Core Code Blueprint (Functional Requirements)
The Python backend must implement a distinct two-step pipeline. Below is the programmatic requirement for handling this workflow:
Step A: The Dynamic Team Architect
This function acts as the supervisor, using Pydantic to guarantee the LLM returns an exact data schema for the new agents.
from pydantic import BaseModel, Field
from typing import List
from crewai import LLM
# 1. Connect to Ollama
ollama_llm = LLM(
model="ollama/llama3.1:8b",
base_url="http://localhost:11434"
)
# 2. Define schema for dynamic team generation
class AgentBlueprint(BaseModel):
role: str = Field(description="The specific role of the agent.")
goal: str = Field(description="What the agent aims to achieve.")
backstory: str = Field(description="The persona and professional experience.")
class TaskBlueprint(BaseModel):
description: str = Field(description="Detailed instructions of what the agent must do.")
expected_output: str = Field(description="Clear explanation of what the final asset looks like.")
assigned_agent_role: str = Field(description="The role of the agent who should execute this.")
class TeamBlueprint(BaseModel):
agents: List[AgentBlueprint]
tasks: List[TaskBlueprint]
Step B: The Dynamic Assembly & Execution Loop
Your application must ingest the Pydantic data structure, map the tasks to the newly minted agents, and kick off the workflow.
from crewai import Agent, Task, Crew, Process
def run_dynamic_team(user_goal: str):
# 1. Ask the Orchestrator LLM to output Structured Data matching TeamBlueprint
# (Using your preferred structured output method or system prompt)
team_structure = orchestrator_llm.generate_structure(
prompt=f"Create an optimal team blueprint to achieve: {user_goal}",
response_model=TeamBlueprint
)
# 2. Dynamically instantiate Agents
created_agents = {}
for a in team_structure.agents:
created_agents[a.role] = Agent(
role=a.role,
goal=a.goal,
backstory=a.backstory,
llm=ollama_llm,
verbose=True
)
# 3. Dynamically instantiate Tasks and link them to the specific Agent
created_tasks = []
for t in team_structure.tasks:
created_tasks.append(
Task(
description=t.description,
expected_output=t.expected_output,
agent=created_agents[t.assigned_agent_role]
)
)
# 4. Assemble and execute the Crew
crew = Crew(
agents=list(created_agents.values()),
tasks=created_tasks,
process=Process.sequential # Or hierarchical if you add a manager agent
)
return crew.kickoff()
4. Guardrails and Context Management
Running multi-agent systems purely on local hardware introduces specific boundaries you must account for:
Context Window Constraints: Local open-source models usually default to a 4k or 8k context window unless explicitly configured otherwise. When multiple agents chat and pass task history back and forth, the window fills up fast. You must use frameworks that offer automated history pruning or set
respect_context_window=True.Structured Output Enforcement: If the Orchestrator outputs raw text instead of valid JSON when defining the team, your Python script will throw a parsing exception. Enforce JSON output modes or use Pydantic validation layers explicitly.
System Compute Scaling: Unlike cloud APIs, running 3 or 4 local agents simultaneously means your CPU/GPU will face sequential or concurrent spikes. A queue system or
max_iterlimit (e.g., maximum 5 loops per task) is required to stop agents from getting stuck in infinite reasoning loops that exhaust local hardware.
Would you like to explore how to integrate specific local tools—like web scrapers or file editors—into these dynamically generated agent profiles?
Add the requirement for using tools
To enable the dynamic agent team to interact with the real world (e.g., search the web, read files, scrape sites, or execute code), the system needs a Tool Registry Mapping Layer.
Because local LLMs cannot spontaneously import Python functions, the Orchestrator must be restricted to a predetermined "menu" of available tools, and the backend must map those text selections to live tool instances.
1. Updated System Architecture: Tool Binding
Your dynamic pipeline now requires three components for tool handling:
A Pre-defined Tool Registry: A Python dictionary mapping string identifiers (e.g.,
"web_search") to actual executable tool objects.Tool Inclusion in the Schema: The Pydantic model must be updated so the Orchestrator LLM can choose which tools to grant to each agent.
Local Tool-Calling LLM Support: The target local LLM must support Native Function Calling (like
llama3.1,mistral, orqwen2.5).
2. Technical Code Blueprint (With Tools)
Below is the implementation required to expose tools to your Orchestrator and dynamically bind them to the created agents at runtime.
Step A: The Tool Registry & Updated Pydantic Schema
First, instantiate your actual tool objects and update the Pydantic blueprints to allow the Orchestrator to assign tools from an explicit whitelist.
from pydantic import BaseModel, Field
from typing import List, Literal
from crewai import LLM
from crewai_tools import SerperDevTool, ScrapeWebsiteTool, FileWriterTool
# 1. Instantiate concrete tools available on the host machine
AVAILABLE_TOOLS = {
"web_search": SerperDevTool(),
"web_scracing": ScrapeWebsiteTool(),
"file_writer": FileWriterTool()
}
# 2. Extract the literal keys for the Pydantic schema
# This restricts the LLM to ONLY picking tools that actually exist in your code
ToolNames = Literal["web_search", "web_scracing", "file_writer"]
class AgentBlueprint(BaseModel):
role: str = Field(description="The specific role of the agent.")
goal: str = Field(description="What the agent aims to achieve.")
backstory: str = Field(description="The persona and professional experience.")
# The Orchestrator can choose 0, 1, or multiple tools for this agent
assigned_tools: List[ToolNames] = Field(
default=[],
description="The tools this agent requires to fulfill its specific goal."
)
class TaskBlueprint(BaseModel):
description: str = Field(description="Detailed instructions of what the agent must do.")
expected_output: str = Field(description="Clear explanation of the final asset.")
assigned_agent_role: str = Field(description="The role of the agent who should execute this.")
class TeamBlueprint(BaseModel):
agents: List[AgentBlueprint]
tasks: List[TaskBlueprint]
Step B: The Dynamic Tool Injection Loop
During the runtime construction loop, the system must cross-reference the text list generated by the Orchestrator against the AVAILABLE_TOOLS registry map.
from crewai import Agent, Task, Crew
def run_dynamic_team_with_tools(user_goal: str):
# Inject the available tools list into the system prompt so the LLM knows its options
tool_options_string = ", ".join(AVAILABLE_TOOLS.keys())
# 1. Ask Orchestrator to generate the structure
team_structure = orchestrator_llm.generate_structure(
prompt=f"Create a team blueprint for: {user_goal}. Available tools to assign: [{tool_options_string}]",
response_model=TeamBlueprint
)
# 2. Dynamically instantiate Agents and map their tools
created_agents = {}
for a in team_structure.agents:
# Look up the real tool objects using the string keys provided by the LLM
real_tools = [AVAILABLE_TOOLS[tool_name] for tool_name in a.assigned_tools if tool_name in AVAILABLE_TOOLS]
created_agents[a.role] = Agent(
role=a.role,
goal=a.goal,
backstory=a.backstory,
tools=real_tools, # Injecting the concrete tools here
llm=ollama_llm,
verbose=True
)
# 3. Instantiate Tasks
created_tasks = []
for t in team_structure.tasks:
created_tasks.append(
Task(
description=t.description,
expected_output=t.expected_output,
agent=created_agents[t.assigned_agent_role]
)
)
# 4. Assemble and execute
crew = Crew(
agents=list(created_agents.values()),
tasks=created_tasks
)
return crew.kickoff()
3. Tool-Specific Local Guardrails
Giving local LLMs tools requires strict structural boundaries to prevent them from crashing or locking up your system:
Function-Calling Model Requirements: Ensure you pass a
function_calling_llmparameter to the Crew or Agent if your main reasoning model struggles with tool syntax. Ollama models likellama3.1:8bhandle basic tools well, but smaller models (likephi3) will often fail to format tool arguments correctly and trigger infinite loops.Maximum Tool Iterations (
max_iter): A local agent might get stuck trying to use a tool repeatedly if it receives an unexpected error (e.g., a website blocking a scraper). You must setmax_iter=5ormax_rpmon theAgentorCrewconfiguration to force the agent to give up and move on if a tool stalls.Argument Validation Guardrails: Local models occasionally hallucinate arguments for tools (e.g., passing a poorly formatted dictionary instead of a single string to a search tool). Custom tools should always wrap their internal logic in
try/exceptblocks that return a clean string error back to the agent (e.g.,"Error: Invalid URL format. Please try again with a valid string URL.") rather than letting the Python application crash.
This structured Product Requirement Document (PRD) is optimized to be pasted directly into an AI-Assisted code generator (such as Cursor, Windsurf, or GitHub Copilot) to build your dynamic Python multi-agent system.
System Prompt & Specification: Dynamic Local Multi-Agent Blueprint System
Project Overview
Build a Python 3.11+ backend application that dynamically generates, configures, and executes custom teams of AI agents using local Ollama LLMs via the CrewAI framework. The application must accept a natural language goal from a user, pass it to an Orchestrator model to design the team, map whitelisted tools, and execute the workflow sequentially.
Technical Stack & Constraints
Language: Python $\ge$ 3.10 and < 3.14
Agent Framework:
crewai(Latest version)LLM Engine: Local Ollama API running on
http://localhost:11434Target Models:
Orchestration/Structuring:
ollama/llama3.1:8b(or high-capability alternative)Agent Reasoning:
ollama/llama3.1:8b(Must support native function calling)
Data Validation:
pydanticv2 for structured output schema enforcement.
Detailed Functional Requirements
1. The Whitelisted Tool Registry
Create a centralized dictionary mapping string identifiers to concrete CrewAI tool instances.
# Permitted Tools Matrix
"web_search" -> SerperDevTool()
"web_scraping" -> ScrapeWebsiteTool()
"file_writer" -> FileWriterTool()
2. Strict Pydantic Schema Specification
Define schemas that enforce structured JSON responses from the Orchestrator LLM:
AgentBlueprint:
role(string, unique identifier)goal(string)backstory(string)assigned_tools(List of Literal strings:"web_search","web_scraping","file_writer")
TaskBlueprint:
description(string)expected_output(string)assigned_agent_role(string, must match an agent'srole)
TeamBlueprint:
agents(List of AgentBlueprint)tasks(List of TaskBlueprint)
3. Execution Pipeline Logic
Implement a main entry function run_dynamic_team(user_goal: str) -> str that executes these phases sequentially:
Phase 1: Team Architecture Generation
Pass the
user_goalalong with a whitelisted string array of available tools to the Orchestrator LLM.Enforce structured extraction matching the
TeamBlueprintschema. Throw a parsing exception if the output fails Pydantic validation.
Phase 2: Dynamic Crew Assembly
Iterate through the generated
agentslist.Map the text strings in
assigned_toolsto the concrete tool objects inside the Tool Registry.Instantiate
crewai.Agentobjects injecting the localollama_llm.Iterate through the
taskslist, instantiatingcrewai.Taskobjects linked to their corresponding generated Agent object.
Phase 3: Assembly & Kickoff
Instantiate a
crewai.Crewpassing the generated agents and tasks.Set the process parameter to
Process.sequential.Execute
.kickoff()and return the final string result.
Non-Functional Guardrails & Error Handling
Infinite Loop Mitigation: Force
max_iter=5on all dynamically generated Agents to prevent local hardware exhaustion if an agent gets stuck in a reasoning loop.Context Window Protection: Explicitly handle context limitations by appending a safety flag to the LLM configurations to prevent runtime token overflow crashes during multi-turn agent execution.
Graceful Tool Failure: Custom tools or mapped tools must execute within a
try/exceptblock. If a tool fails (e.g., HTTP 403 error during web scraping), it must return the error string back to the agent as text context rather than crashing the core Python process.Missing Agent Reference Catching: Include a pre-flight validation check before launching the Crew: if a Task specifies an
assigned_agent_rolethat does not exist in the generated Agents list, raise a standardValueErrorexplicitly detailing the missing dependency.
Output Verification Target
The final script must run cleanly from the command line:
python main.py --goal "Research the top 3 machine learning trends in 2026, compile a summary file, and save it locally."
It should log the dynamic creation of the agents, the tools assigned to them, and output the final file without throwing schema alignment or connection timeout exceptions.
From <> Google Gemini (3.5 Flash)
Comments
Post a Comment