-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
fix: resolve issue #1338 #1340
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: resolve issue #1338 #1340
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| framework: ag2 | ||
| topic: "Research the latest developments in AI agents" | ||
|
|
||
| # Install: pip install "praisonai[ag2]" | ||
| # Run: praisonai --framework ag2 examples/ag2/ag2_basic.yaml | ||
| # or praisonai run examples/ag2/ag2_basic.yaml --framework ag2 | ||
|
|
||
| roles: | ||
| research_agent: | ||
| role: "AI Research Specialist" | ||
| goal: "Research and summarise the latest developments in AI agent frameworks" | ||
| backstory: | | ||
| You are an experienced AI researcher with deep knowledge of multi-agent | ||
| systems, large language models, and the latest trends in AI tooling. | ||
| You excel at synthesising complex technical topics into clear summaries. | ||
| tasks: | ||
| research_task: | ||
| description: | | ||
| Research and summarise the latest developments in AI agent frameworks | ||
| for the topic: {topic} | ||
|
|
||
| Focus on: | ||
| 1. Key frameworks and their unique capabilities | ||
| 2. Recent innovations and improvements | ||
| 3. Community adoption and ecosystem growth | ||
| 4. Practical use cases and success stories | ||
| expected_output: | | ||
| A concise research summary covering the key developments, | ||
| major frameworks, and practical insights. Include 3-5 bullet | ||
| points of the most important findings. | ||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,42 @@ | ||||||
| framework: ag2 | ||||||
| topic: "Cloud-native AI deployment strategies on AWS" | ||||||
|
|
||||||
| # AG2 exclusive feature: native AWS Bedrock support via LLMConfig(api_type="bedrock") | ||||||
| # | ||||||
| # Prerequisites: | ||||||
| # pip install "praisonai[ag2]" | ||||||
| # aws configure (or set AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_DEFAULT_REGION) | ||||||
| # | ||||||
| # Run: | ||||||
| # praisonai --framework ag2 examples/ag2/ag2_bedrock.yaml | ||||||
| # | ||||||
|
Comment on lines
+10
to
+12
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 1. Cli rejects ag2 option Examples instruct users to run praisonai --framework ag2 ..., but the CLI parser only allows crewai|autogen|praisonai, so AG2 cannot be used from the CLI as documented. Agent Prompt
Comment on lines
+10
to
+12
|
||||||
| # The AG2 adapter detects api_type="bedrock" from the llm config and uses | ||||||
| # LLMConfig(api_type="bedrock", model=...) — no OPENAI_API_KEY required. | ||||||
| # AWS credentials are sourced from boto3 (env vars, ~/.aws/credentials, IAM role). | ||||||
|
|
||||||
| roles: | ||||||
| cloud_architect: | ||||||
| role: "AWS Cloud Architect" | ||||||
| goal: "Design and explain cloud-native AI deployment strategies on AWS" | ||||||
| backstory: | | ||||||
| You are an AWS Solutions Architect specialising in AI/ML workloads. | ||||||
| You have deep expertise in Amazon Bedrock, SageMaker, ECS, and Lambda, | ||||||
| and you help organisations deploy AI agents at scale securely and cost-effectively. | ||||||
| llm: | ||||||
| model: "bedrock/anthropic.claude-3-5-sonnet-20241022-v2:0" | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| api_type: "bedrock" | ||||||
| aws_region: "us-east-1" | ||||||
|
Comment on lines
+25
to
+28
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Check if aws_region is handled in _run_ag2
rg -n "aws_region" src/praisonai/praisonai/agents_generator.pyRepository: MervinPraison/PraisonAI Length of output: 49 🏁 Script executed: # Search for _run_ag2 function definition
rg -n "def _run_ag2" src/praisonai/Repository: MervinPraison/PraisonAI Length of output: 165 🏁 Script executed: # Search for how llm config dict is being processed
rg -n "llm\[" src/praisonai/praisonai/agents_generator.py | head -20Repository: MervinPraison/PraisonAI Length of output: 49 🏁 Script executed: # Look for LLMConfig instantiation with bedrock
rg -n "LLMConfig" src/praisonai/praisonai/agents_generator.py | head -20Repository: MervinPraison/PraisonAI Length of output: 500 🏁 Script executed: # Search for bedrock or aws handling in the codebase
rg -n "bedrock" src/praisonai/ -i | head -20Repository: MervinPraison/PraisonAI Length of output: 2028 🏁 Script executed: # Read the relevant section around line 474-483
sed -n '470,495p' src/praisonai/praisonai/agents_generator.pyRepository: MervinPraison/PraisonAI Length of output: 1239 🏁 Script executed: # Check what's in llm_config_entry before LLMConfig is called
sed -n '428,500p' src/praisonai/praisonai/agents_generator.py | head -80Repository: MervinPraison/PraisonAI Length of output: 3384 🏁 Script executed: # Check the test to understand expected behavior
cat -n src/praisonai/tests/unit/test_ag2_adapter.py | sed -n '197,240p'Repository: MervinPraison/PraisonAI Length of output: 2378 🌐 Web query:
💡 Result: In AG2 (AutoGen), the Bedrock region is set via the from autogen import LLMConfig
llm_config = LLMConfig(
config_list={
"api_type": "bedrock",
"model": "anthropic.claude-3-5-sonnet-20241022-v2:0",
"aws_region": "us-east-1",
"aws_access_key": "...",
"aws_secret_key": "...",
# optional: "aws_session_token": "...",
# optional: "aws_profile_name": "default",
}
)AG2’s Bedrock examples also show pulling it from env, e.g. Sources: AG2 Amazon Bedrock guide [1], AG2 Bedrock structured output notebook [2]. 🏁 Script executed: # Check if aws_region is mentioned anywhere in the repository in context of LLMConfig
rg -n "aws_region" src/praisonai/ -A 2 -B 2Repository: MervinPraison/PraisonAI Length of output: 49 🏁 Script executed: # Check if there are any other bedrock config examples in the repo
fd -e yaml -o -e yml | xargs grep -l "bedrock" 2>/dev/nullRepository: MervinPraison/PraisonAI Length of output: 185 🏁 Script executed: # Look for any bedrock-related documentation or comments in the code
rg -n "Bedrock" src/praisonai/praisonai/agents_generator.py -A 3 -B 3Repository: MervinPraison/PraisonAI Length of output: 407 Extract and propagate The Update if api_type == "bedrock":
aws_region = _resolve("aws_region", env_var="AWS_DEFAULT_REGION", default="us-east-1")
llm_config_entry = {"api_type": "bedrock", "model": model_name, "aws_region": aws_region}🤖 Prompt for AI Agents |
||||||
| tasks: | ||||||
| architecture_task: | ||||||
| description: | | ||||||
| Design a cloud-native deployment strategy for AI agents on AWS for: {topic} | ||||||
|
|
||||||
| Cover: | ||||||
| 1. Recommended AWS services (Bedrock, ECS, Lambda, etc.) | ||||||
| 2. Scalability and cost optimisation patterns | ||||||
| 3. Security and compliance considerations | ||||||
| 4. A simple reference architecture overview | ||||||
| expected_output: | | ||||||
| A concise architecture guide with service recommendations, | ||||||
| a high-level deployment diagram description, and key | ||||||
| best practices for production AI agent deployments on AWS. | ||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| framework: ag2 | ||
| topic: "The impact of open-source AI on enterprise software development" | ||
|
|
||
| # Install: pip install "praisonai[ag2]" | ||
| # Run: praisonai --framework ag2 examples/ag2/ag2_multi_agent.yaml | ||
| # or praisonai run examples/ag2/ag2_multi_agent.yaml --framework ag2 | ||
|
Comment on lines
+4
to
+6
|
||
| # | ||
| # This example demonstrates AG2's GroupChat multi-agent coordination. | ||
| # Both agents participate in a collaborative conversation managed by | ||
| # a GroupChatManager until the task is complete. | ||
|
|
||
| roles: | ||
| researcher: | ||
| role: "Research Specialist" | ||
| goal: "Gather and analyse information on the given topic" | ||
| backstory: | | ||
| You are a meticulous researcher who excels at finding relevant | ||
| information, analysing trends, and presenting data-backed insights. | ||
| You always cite your reasoning and structure your findings clearly. | ||
| tasks: | ||
| research_task: | ||
| description: | | ||
| Research the topic: {topic} | ||
|
|
||
| Investigate: | ||
| 1. Current state and adoption rates | ||
| 2. Key players and projects driving the trend | ||
| 3. Technical advantages and challenges | ||
| 4. Business impact and cost implications | ||
| expected_output: | | ||
| A structured research briefing with findings on the topic, | ||
| including key data points, trends, and technical observations. | ||
|
|
||
| writer: | ||
| role: "Technical Content Writer" | ||
| goal: "Transform research findings into clear, engaging written content" | ||
| backstory: | | ||
| You are a skilled technical writer who turns complex research into | ||
| accessible, well-structured articles. You focus on clarity, logical | ||
| flow, and actionable takeaways for a professional audience. | ||
| tasks: | ||
| writing_task: | ||
| description: | | ||
| Using the research findings provided by the Research Specialist, | ||
| write a concise article on: {topic} | ||
|
|
||
| The article should: | ||
| 1. Open with a compelling hook | ||
| 2. Present key findings logically | ||
| 3. Include practical implications for developers | ||
| 4. Close with a forward-looking conclusion | ||
| expected_output: | | ||
| A 400-500 word article suitable for a technical blog, | ||
| with clear sections, professional tone, and concrete takeaways. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,16 @@ | ||
| OPENAI_MODEL_NAME="gpt-4o" | ||
| # OpenAI / compatible API | ||
| OPENAI_API_KEY="Enter your API key" | ||
| OPENAI_MODEL_NAME="gpt-4o" | ||
| OPENAI_API_BASE="https://api.openai.com/v1" | ||
|
|
||
| # AG2 framework (uses same OPENAI_* vars above, or override below) | ||
| # MODEL_NAME=gpt-4o-mini | ||
|
|
||
| # AWS Bedrock (for ag2_bedrock.yaml example) | ||
| # AWS_DEFAULT_REGION=us-east-1 | ||
| # AWS_ACCESS_KEY_ID=your-access-key | ||
| # AWS_SECRET_ACCESS_KEY=your-secret-key | ||
|
|
||
| # Chainlit (optional) | ||
| CHAINLIT_USERNAME=admin | ||
| CHAINLIT_USERNAME=admin | ||
| CHAINLIT_AUTH_SECRET="chainlit create-secret to create" | ||
| CHAINLIT_AUTH_SECRET="chainlit create-secret to create" |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -41,6 +41,16 @@ | |||||||||||||||||||||||||||
| except ImportError: | ||||||||||||||||||||||||||||
| pass | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| AG2_AVAILABLE = False | ||||||||||||||||||||||||||||
| try: | ||||||||||||||||||||||||||||
| import importlib.metadata as _importlib_metadata | ||||||||||||||||||||||||||||
| _importlib_metadata.distribution('ag2') | ||||||||||||||||||||||||||||
| from autogen import LLMConfig as _AG2LLMConfig # noqa: F401 — AG2-exclusive class | ||||||||||||||||||||||||||||
|
Comment on lines
+44
to
+48
|
||||||||||||||||||||||||||||
| AG2_AVAILABLE = True | ||||||||||||||||||||||||||||
| del _AG2LLMConfig, _importlib_metadata | ||||||||||||||||||||||||||||
| except Exception: | ||||||||||||||||||||||||||||
| pass | ||||||||||||||||||||||||||||
|
Comment on lines
+51
to
+52
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Catching a generic
Suggested change
|
||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| try: | ||||||||||||||||||||||||||||
| import agentops | ||||||||||||||||||||||||||||
| AGENTOPS_AVAILABLE = True | ||||||||||||||||||||||||||||
|
|
@@ -51,7 +61,7 @@ | |||||||||||||||||||||||||||
| pass | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| # Only try to import praisonai_tools if either CrewAI or AutoGen is available | ||||||||||||||||||||||||||||
| if CREWAI_AVAILABLE or AUTOGEN_AVAILABLE or PRAISONAI_AVAILABLE: | ||||||||||||||||||||||||||||
| if CREWAI_AVAILABLE or AUTOGEN_AVAILABLE or PRAISONAI_AVAILABLE or AG2_AVAILABLE: | ||||||||||||||||||||||||||||
| try: | ||||||||||||||||||||||||||||
| from praisonai_tools import ( | ||||||||||||||||||||||||||||
| CodeDocsSearchTool, CSVSearchTool, DirectorySearchTool, DOCXSearchTool, DirectoryReadTool, | ||||||||||||||||||||||||||||
|
|
@@ -127,6 +137,8 @@ def __init__(self, agent_file, framework, config_list, log_level=None, agent_cal | |||||||||||||||||||||||||||
| raise ImportError("AutoGen is not installed. Please install it with 'pip install praisonai[autogen]'") | ||||||||||||||||||||||||||||
| elif framework == "praisonai" and not PRAISONAI_AVAILABLE: | ||||||||||||||||||||||||||||
| raise ImportError("PraisonAI is not installed. Please install it with 'pip install praisonaiagents'") | ||||||||||||||||||||||||||||
| elif framework == "ag2" and not AG2_AVAILABLE: | ||||||||||||||||||||||||||||
| raise ImportError("AG2 is not installed. Please install it with 'pip install praisonai[ag2]'") | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| def is_function_or_decorated(self, obj): | ||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||
|
|
@@ -274,7 +286,7 @@ def generate_crew_and_kickoff(self): | |||||||||||||||||||||||||||
| tools_dict = {} | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| # Only try to use praisonai_tools if it's available and needed | ||||||||||||||||||||||||||||
| if PRAISONAI_TOOLS_AVAILABLE and (CREWAI_AVAILABLE or AUTOGEN_AVAILABLE or PRAISONAI_AVAILABLE): | ||||||||||||||||||||||||||||
| if PRAISONAI_TOOLS_AVAILABLE and (CREWAI_AVAILABLE or AUTOGEN_AVAILABLE or PRAISONAI_AVAILABLE or AG2_AVAILABLE): | ||||||||||||||||||||||||||||
| tools_dict = { | ||||||||||||||||||||||||||||
| 'CodeDocsSearchTool': CodeDocsSearchTool(), | ||||||||||||||||||||||||||||
| 'CSVSearchTool': CSVSearchTool(), | ||||||||||||||||||||||||||||
|
|
@@ -327,6 +339,12 @@ def generate_crew_and_kickoff(self): | |||||||||||||||||||||||||||
| if AGENTOPS_AVAILABLE: | ||||||||||||||||||||||||||||
| agentops.init(os.environ.get("AGENTOPS_API_KEY"), default_tags=["praisonai"]) | ||||||||||||||||||||||||||||
| return self._run_praisonai(config, topic, tools_dict) | ||||||||||||||||||||||||||||
| elif framework == "ag2": | ||||||||||||||||||||||||||||
| if not AG2_AVAILABLE: | ||||||||||||||||||||||||||||
| raise ImportError("AG2 is not installed. Please install it with 'pip install praisonai[ag2]'") | ||||||||||||||||||||||||||||
| if AGENTOPS_AVAILABLE: | ||||||||||||||||||||||||||||
| agentops.init(os.environ.get("AGENTOPS_API_KEY"), default_tags=["ag2"]) | ||||||||||||||||||||||||||||
| return self._run_ag2(config, topic, tools_dict) | ||||||||||||||||||||||||||||
| else: # framework=crewai | ||||||||||||||||||||||||||||
| if not CREWAI_AVAILABLE: | ||||||||||||||||||||||||||||
| raise ImportError("CrewAI is not installed. Please install it with 'pip install praisonai[crewai]'") | ||||||||||||||||||||||||||||
|
|
@@ -407,6 +425,150 @@ def _run_autogen(self, config, topic, tools_dict): | |||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| return result | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| def _run_ag2(self, config, topic, tools_dict): | ||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||
| Run agents using the AG2 framework (community fork of AutoGen, PyPI: ag2). | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| AG2 installs under the 'autogen' namespace — there is no 'import ag2'. | ||||||||||||||||||||||||||||
| Uses LLMConfig context manager + AssistantAgent + GroupChat pattern. | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| Args: | ||||||||||||||||||||||||||||
| config (dict): Configuration dictionary parsed from YAML | ||||||||||||||||||||||||||||
| topic (str): The topic/task to process | ||||||||||||||||||||||||||||
| tools_dict (dict): Dictionary of available tools | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| Returns: | ||||||||||||||||||||||||||||
| str: Result prefixed with '### AG2 Output ###' | ||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||
| import re | ||||||||||||||||||||||||||||
| from autogen import ( | ||||||||||||||||||||||||||||
| AssistantAgent, UserProxyAgent, GroupChat, GroupChatManager, LLMConfig | ||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| model_config = self.config_list[0] if self.config_list else {} | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| # Allow YAML top-level llm block to override config_list values | ||||||||||||||||||||||||||||
| yaml_llm = config.get("llm", {}) or {} | ||||||||||||||||||||||||||||
| # Also check first role's llm block as a fallback | ||||||||||||||||||||||||||||
| first_role_llm = {} | ||||||||||||||||||||||||||||
| for role_details in config.get("roles", {}).values(): | ||||||||||||||||||||||||||||
| first_role_llm = role_details.get("llm", {}) or {} | ||||||||||||||||||||||||||||
| break | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| # Priority: YAML top-level llm > first role llm > config_list > env vars | ||||||||||||||||||||||||||||
| def _resolve(key, env_var=None, default=None): | ||||||||||||||||||||||||||||
| return (yaml_llm.get(key) or first_role_llm.get(key) | ||||||||||||||||||||||||||||
| or model_config.get(key) | ||||||||||||||||||||||||||||
| or (os.environ.get(env_var) if env_var else None) | ||||||||||||||||||||||||||||
| or default) | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| api_type = _resolve("api_type", default="openai").lower() | ||||||||||||||||||||||||||||
| model_name = _resolve("model", default="gpt-4o-mini") | ||||||||||||||||||||||||||||
| api_key = _resolve("api_key", env_var="OPENAI_API_KEY") | ||||||||||||||||||||||||||||
| # Fix #3: also check OPENAI_API_BASE for consistency with rest of codebase | ||||||||||||||||||||||||||||
| base_url = (model_config.get("base_url") | ||||||||||||||||||||||||||||
| or yaml_llm.get("base_url") | ||||||||||||||||||||||||||||
| or os.environ.get("OPENAI_BASE_URL") | ||||||||||||||||||||||||||||
| or os.environ.get("OPENAI_API_BASE")) | ||||||||||||||||||||||||||||
|
Comment on lines
+469
to
+472
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
All other config fields (model, api_key, api_type) are resolved via the
Suggested change
Comment on lines
+450
to
+472
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 3. Base_url override wrong order _run_ag2 documents that YAML llm overrides config_list, but base_url is resolved with config_list taking precedence, so YAML llm.base_url is silently ignored. Agent Prompt
|
||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| # Build LLMConfig — pass a config dict; Bedrock needs no api_key | ||||||||||||||||||||||||||||
| if api_type == "bedrock": | ||||||||||||||||||||||||||||
| llm_config_entry = {"api_type": "bedrock", "model": model_name} | ||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||
|
Comment on lines
+474
to
+477
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 2. Bedrock region ignored _run_ag2 drops the YAML aws_region setting for Bedrock, so the ag2_bedrock.yaml example’s explicit region is never applied. Agent Prompt
|
||||||||||||||||||||||||||||
| llm_config_entry = {"model": model_name} | ||||||||||||||||||||||||||||
| if api_key: | ||||||||||||||||||||||||||||
| llm_config_entry["api_key"] = api_key | ||||||||||||||||||||||||||||
| if base_url and base_url not in ("https://api.openai.com/v1", "https://api.openai.com/v1/"): | ||||||||||||||||||||||||||||
| llm_config_entry["base_url"] = base_url | ||||||||||||||||||||||||||||
|
Comment on lines
+475
to
+482
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The To honour the YAML setting:
Suggested change
|
||||||||||||||||||||||||||||
| llm_config = LLMConfig(llm_config_entry) | ||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Because the unit tests mock
Suggested change
|
||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| user_proxy = UserProxyAgent( | ||||||||||||||||||||||||||||
| name="User", | ||||||||||||||||||||||||||||
| human_input_mode="NEVER", | ||||||||||||||||||||||||||||
| is_termination_msg=lambda x: "TERMINATE" in (x.get("content") or ""), | ||||||||||||||||||||||||||||
| code_execution_config=False, | ||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| # Create one AssistantAgent per role, passing llm_config directly | ||||||||||||||||||||||||||||
| ag2_agent_entries = [] | ||||||||||||||||||||||||||||
| for role, details in config["roles"].items(): | ||||||||||||||||||||||||||||
| agent_name = details.get("role", role).replace("{topic}", topic) | ||||||||||||||||||||||||||||
| backstory = details.get("backstory", "").replace("{topic}", topic) | ||||||||||||||||||||||||||||
| agent_name_safe = re.sub(r"[^a-zA-Z0-9_\-]", "_", agent_name) | ||||||||||||||||||||||||||||
| assistant = AssistantAgent( | ||||||||||||||||||||||||||||
| name=agent_name_safe, | ||||||||||||||||||||||||||||
| system_message=backstory + "\nWhen the task is done, reply 'TERMINATE'.", | ||||||||||||||||||||||||||||
| llm_config=llm_config, | ||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||
| ag2_agent_entries.append((role, details, assistant)) | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| # Register tools via AG2 decorator pattern | ||||||||||||||||||||||||||||
| for role, details, assistant in ag2_agent_entries: | ||||||||||||||||||||||||||||
| for tool_name in details.get("tools", []): | ||||||||||||||||||||||||||||
| tool = tools_dict.get(tool_name) | ||||||||||||||||||||||||||||
| if tool is None: | ||||||||||||||||||||||||||||
| continue | ||||||||||||||||||||||||||||
| func = tool if callable(tool) else getattr(tool, "run", None) | ||||||||||||||||||||||||||||
| if func is None: | ||||||||||||||||||||||||||||
| continue | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| def make_tool_fn(f): | ||||||||||||||||||||||||||||
| def tool_fn(**kwargs): | ||||||||||||||||||||||||||||
| return f(**kwargs) if callable(f) else str(f) | ||||||||||||||||||||||||||||
| tool_fn.__name__ = tool_name | ||||||||||||||||||||||||||||
|
Comment on lines
+515
to
+518
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The
Suggested change
|
||||||||||||||||||||||||||||
| return tool_fn | ||||||||||||||||||||||||||||
|
Comment on lines
+515
to
+519
|
||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| wrapped = make_tool_fn(func) | ||||||||||||||||||||||||||||
| assistant.register_for_llm(description=f"Tool: {tool_name}")(wrapped) | ||||||||||||||||||||||||||||
| user_proxy.register_for_execution()(wrapped) | ||||||||||||||||||||||||||||
|
Comment on lines
+515
to
+523
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Closure captures loop variable by reference — all tools will share the last The 🐛 Proposed fix- def make_tool_fn(f):
+ def make_tool_fn(f, name=tool_name):
def tool_fn(**kwargs):
return f(**kwargs) if callable(f) else str(f)
- tool_fn.__name__ = tool_name
+ tool_fn.__name__ = name
return tool_fn🧰 Tools🪛 Ruff (0.15.9)[warning] 518-518: Function definition does not bind loop variable (B023) 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| all_assistants = [a for _, _, a in ag2_agent_entries] | ||||||||||||||||||||||||||||
| if not all_assistants: | ||||||||||||||||||||||||||||
| return "### AG2 Output ###\nNo agents created from configuration." | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| # Build initial message from all task descriptions | ||||||||||||||||||||||||||||
| task_lines = [] | ||||||||||||||||||||||||||||
| for role, details, _ in ag2_agent_entries: | ||||||||||||||||||||||||||||
| for task_name, task_details in details.get("tasks", {}).items(): | ||||||||||||||||||||||||||||
| desc = task_details.get("description", "").replace("{topic}", topic) | ||||||||||||||||||||||||||||
| if desc: | ||||||||||||||||||||||||||||
| task_lines.append(desc) | ||||||||||||||||||||||||||||
| initial_message = "\n".join(task_lines) if task_lines else topic | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| groupchat = GroupChat( | ||||||||||||||||||||||||||||
| agents=[user_proxy] + all_assistants, | ||||||||||||||||||||||||||||
| messages=[], | ||||||||||||||||||||||||||||
| max_round=12, | ||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||
| manager = GroupChatManager(groupchat=groupchat, llm_config=llm_config) | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| try: | ||||||||||||||||||||||||||||
| chat_result = user_proxy.initiate_chat(manager, message=initial_message) | ||||||||||||||||||||||||||||
| except Exception as e: | ||||||||||||||||||||||||||||
| return f"### AG2 Error ###\n{str(e)}" | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| # Prefer ChatResult.summary if available, otherwise scan messages | ||||||||||||||||||||||||||||
| result_content = "" | ||||||||||||||||||||||||||||
| summary = getattr(chat_result, "summary", None) | ||||||||||||||||||||||||||||
| if summary and isinstance(summary, str) and summary.strip(): | ||||||||||||||||||||||||||||
| result_content = re.sub(r'[\s\.\,]*TERMINATE[\s\.\,]*$', '', summary, flags=re.IGNORECASE).strip().rstrip('.') | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| if not result_content: | ||||||||||||||||||||||||||||
| for msg in reversed(groupchat.messages): | ||||||||||||||||||||||||||||
| # Skip the initial user proxy message | ||||||||||||||||||||||||||||
| if msg.get("name") == "User": | ||||||||||||||||||||||||||||
| continue | ||||||||||||||||||||||||||||
| content = (msg.get("content") or "").strip() | ||||||||||||||||||||||||||||
| if content: | ||||||||||||||||||||||||||||
| result_content = re.sub(r'[\s\.\,]*TERMINATE[\s\.\,]*$', '', content, flags=re.IGNORECASE).strip().rstrip('.') | ||||||||||||||||||||||||||||
| if result_content: | ||||||||||||||||||||||||||||
| break | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| if not result_content: | ||||||||||||||||||||||||||||
| result_content = "Task completed." | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| return f"### AG2 Output ###\n{result_content}" | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| def _run_crewai(self, config, topic, tools_dict): | ||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||
| Run agents using the CrewAI framework. | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -32,6 +32,16 @@ | |||||||||
| except ImportError: | ||||||||||
| pass | ||||||||||
|
|
||||||||||
| AG2_AVAILABLE = False | ||||||||||
| try: | ||||||||||
| import importlib.metadata as _importlib_metadata | ||||||||||
| _importlib_metadata.distribution('ag2') | ||||||||||
| from autogen import LLMConfig as _AG2LLMConfig # noqa: F401 — AG2-exclusive class | ||||||||||
| AG2_AVAILABLE = True | ||||||||||
| del _AG2LLMConfig, _importlib_metadata | ||||||||||
| except Exception: | ||||||||||
| pass | ||||||||||
|
Comment on lines
+42
to
+43
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Catching a generic
Suggested change
|
||||||||||
|
|
||||||||||
| try: | ||||||||||
| from praisonai_tools import ( | ||||||||||
| CodeDocsSearchTool, CSVSearchTool, DirectorySearchTool, DOCXSearchTool, | ||||||||||
|
|
@@ -83,6 +93,11 @@ def __init__(self, topic="Movie Story writing about AI", agent_file="test.yaml", | |||||||||
| Praisonai is not installed. Please install with: | ||||||||||
| pip install praisonaiagents | ||||||||||
| """) | ||||||||||
| elif framework == "ag2" and not AG2_AVAILABLE: | ||||||||||
| raise ImportError(""" | ||||||||||
| AG2 is not installed. Please install with: | ||||||||||
| pip install "praisonai[ag2]" | ||||||||||
| """) | ||||||||||
|
|
||||||||||
| # Only show tools message if using a framework and tools are needed | ||||||||||
| if (framework in ["crewai", "autogen"]) and not PRAISONAI_TOOLS_AVAILABLE: | ||||||||||
|
|
||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This example instructs users to pass
--framework ag2, but the CLI currently restricts--frameworkchoices to["crewai", "autogen", "praisonai"](praisonai/cli.py). Either update the CLI/UI to acceptag2, or adjust these run instructions to omit--frameworkand rely onframework: ag2in the YAML.