From e45e53aa5cfea5b628868c590c092cd5d2e0e130 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Wed, 3 Sep 2025 00:45:31 +0000 Subject: [PATCH 1/2] Add Agno Research Agent converted to Agentuity - Convert https://docs.agno.com/examples/agents/research-agent to Agentuity - Preserve original Agno framework code in research_agent.py - Add Agentuity wrapper following established patterns - Include comprehensive configuration and documentation - Support for DuckDuckGo search and Newspaper4k content analysis - Professional NYT-style investigative reporting capabilities Co-Authored-By: Dhilan Fye --- frameworks/agno/research-agent/.editorconfig | 18 +++ frameworks/agno/research-agent/.gitignore | 132 ++++++++++++++++++ frameworks/agno/research-agent/README.md | 97 +++++++++++++ .../agents/ResearchAgent/agent.py | 45 ++++++ .../agents/ResearchAgent/research_agent.py | 94 +++++++++++++ frameworks/agno/research-agent/agentuity.yaml | 62 ++++++++ frameworks/agno/research-agent/pyproject.toml | 12 ++ .../agno/research-agent/requirements.txt | 4 + frameworks/agno/research-agent/server.py | 9 ++ 9 files changed, 473 insertions(+) create mode 100644 frameworks/agno/research-agent/.editorconfig create mode 100644 frameworks/agno/research-agent/.gitignore create mode 100644 frameworks/agno/research-agent/README.md create mode 100644 frameworks/agno/research-agent/agents/ResearchAgent/agent.py create mode 100644 frameworks/agno/research-agent/agents/ResearchAgent/research_agent.py create mode 100644 frameworks/agno/research-agent/agentuity.yaml create mode 100644 frameworks/agno/research-agent/pyproject.toml create mode 100644 frameworks/agno/research-agent/requirements.txt create mode 100644 frameworks/agno/research-agent/server.py diff --git a/frameworks/agno/research-agent/.editorconfig b/frameworks/agno/research-agent/.editorconfig new file mode 100644 index 00000000..bd648257 --- /dev/null +++ b/frameworks/agno/research-agent/.editorconfig @@ -0,0 +1,18 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_style = space +indent_size = 4 +insert_final_newline = true +trim_trailing_whitespace = true + +[*.{yml,yaml}] +indent_size = 2 + +[*.{json,js,ts}] +indent_size = 2 + +[*.md] +trim_trailing_whitespace = false diff --git a/frameworks/agno/research-agent/.gitignore b/frameworks/agno/research-agent/.gitignore new file mode 100644 index 00000000..2cb33bba --- /dev/null +++ b/frameworks/agno/research-agent/.gitignore @@ -0,0 +1,132 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +.python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# UV +uv.lock diff --git a/frameworks/agno/research-agent/README.md b/frameworks/agno/research-agent/README.md new file mode 100644 index 00000000..ed17f7a3 --- /dev/null +++ b/frameworks/agno/research-agent/README.md @@ -0,0 +1,97 @@ +
+ Agentuity
+ Build Agents, Not Infrastructure
+
+ + + +
+
+ +# Agno Research Agent for Agentuity + +This example demonstrates how to convert an [Agno Research Agent](https://docs.agno.com/examples/agents/research-agent) to work with the Agentuity platform while preserving all original framework functionality. + +## Overview + +The Research Agent is a sophisticated AI journalist that combines web search capabilities with advanced content analysis to produce professional-grade investigative reports. It performs comprehensive research using multiple sources, fact-checks information, and delivers polished, New York Times-style articles on any topic. + +**Original Agno Agent**: https://docs.agno.com/examples/agents/research-agent + +## Key Features + +- **Advanced Web Search**: Uses DuckDuckGo for comprehensive topic research +- **Content Analysis**: Leverages Newspaper4k for article extraction and analysis +- **Professional Reporting**: Generates NYT-style investigative articles +- **Multi-source Verification**: Cross-references facts across multiple sources +- **Structured Output**: Delivers well-formatted reports with sections for findings, analysis, and sources + +## Architecture + +This implementation follows the Agentuity framework wrapper pattern: + +1. **Original Agno Agent** (`research_agent.py`): Preserves the complete original Agno implementation +2. **Agentuity Wrapper** (`agent.py`): Provides the Agentuity interface while calling the original agent +3. **Framework Integration**: Maintains all Agno tools, models, and configurations + +## Example Usage + +```python +# The agent accepts research topics and generates comprehensive reports +"Analyze the impact of AI on healthcare delivery and patient outcomes" +"Report on the latest breakthroughs in quantum computing" +"Investigate the global transition to renewable energy sources" +``` + +## Dependencies + +- **Agno**: Core framework for the research agent +- **DuckDuckGo Search**: Web search capabilities +- **Newspaper4k**: Content extraction and analysis +- **Agentuity SDK**: Platform integration + +## 📋 Prerequisites + +Before you begin, ensure you have the following installed: + +- **Python**: Version 3.10 or higher +- **UV**: Version 0.5.25 or higher ([Documentation](https://docs.astral.sh/uv/)) + +## 🚀 Getting Started + +1. Install dependencies: + ```bash + uv sync + ``` + +2. Set up environment variables (create `.env` file): + ```bash + OPENAI_API_KEY=your_openai_api_key_here + ``` + +3. Run the development server: + ```bash + agentuity dev + ``` + +4. Test the agent in the Agentuity Console or deploy to production: + ```bash + agentuity deploy + ``` + +## 📖 Documentation + +For comprehensive documentation on the Agentuity Python SDK, visit: +[https://agentuity.dev/SDKs/python](https://agentuity.dev/SDKs/python) + +## 🆘 Troubleshooting + +If you encounter any issues: + +1. Check the [documentation](https://agentuity.dev/SDKs/python) +2. Join our [Discord community](https://discord.gg/agentuity) for support +3. Contact the Agentuity support team + +## 📝 License + +This project is licensed under the terms specified in the LICENSE file. diff --git a/frameworks/agno/research-agent/agents/ResearchAgent/agent.py b/frameworks/agno/research-agent/agents/ResearchAgent/agent.py new file mode 100644 index 00000000..d78c0572 --- /dev/null +++ b/frameworks/agno/research-agent/agents/ResearchAgent/agent.py @@ -0,0 +1,45 @@ +from agentuity import AgentRequest, AgentResponse, AgentContext +import asyncio + +from agents.ResearchAgent.research_agent import research_agent + +def welcome(): + return { + "welcome": "📰 I'm a Research Agent powered by Agno. Give me a topic and I'll deliver a professional-grade investigative article with comprehensive research and analysis.", + "examples": [ + "Analyze the impact of AI on healthcare delivery and patient outcomes", + "Report on the latest breakthroughs in quantum computing", + "Investigate the global transition to renewable energy sources", + "Explore the evolution of cybersecurity threats and defenses", + "Research the development of autonomous vehicle technology" + ] + } + +async def run(request: AgentRequest, response: AgentResponse, context: AgentContext): + try: + prompt = await request.data.text() + context.logger.info(f"[ResearchAgent] Received research topic: {prompt!r}") + + loop = asyncio.get_running_loop() + raw_result = await loop.run_in_executor(None, lambda: research_agent.run(prompt)) + + if isinstance(raw_result, str): + output = raw_result + elif hasattr(raw_result, "content"): + output = raw_result.content + elif hasattr(raw_result, "reply"): + output = raw_result.reply + else: + output = str(raw_result) + + if not output.strip(): + context.logger.error("[ResearchAgent] Empty output from Agno agent") + return response.text("⚠️ Unable to generate research report. Please try again with a more specific topic.") + + context.logger.info(f"[ResearchAgent] Successfully generated report of {len(output)} characters") + + return response.text(output) + + except Exception as exc: + context.logger.error(f"[ResearchAgent] Error during research: {exc}", exc_info=True) + return response.text("❌ An error occurred while conducting research. Please try again with a different topic.") diff --git a/frameworks/agno/research-agent/agents/ResearchAgent/research_agent.py b/frameworks/agno/research-agent/agents/ResearchAgent/research_agent.py new file mode 100644 index 00000000..fc4efb29 --- /dev/null +++ b/frameworks/agno/research-agent/agents/ResearchAgent/research_agent.py @@ -0,0 +1,94 @@ +from textwrap import dedent + +from agno.agent import Agent +from agno.models.openai import OpenAIChat +from agno.tools.duckduckgo import DuckDuckGoTools +from agno.tools.newspaper4k import Newspaper4kTools + +# Initialize the research agent with advanced journalistic capabilities +research_agent = Agent( + model=OpenAIChat(id="gpt-4o"), + tools=[DuckDuckGoTools(), Newspaper4kTools()], + description=dedent("""\ + You are an elite investigative journalist with decades of experience at the New York Times. + Your expertise encompasses: 📰 + + - Deep investigative research and analysis + - Meticulous fact-checking and source verification + - Compelling narrative construction + - Data-driven reporting and visualization + - Expert interview synthesis + - Trend analysis and future predictions + - Complex topic simplification + - Ethical journalism practices + - Balanced perspective presentation + - Global context integration + """), + instructions=dedent("""\ + 1. Research Phase 🔍 + - Search for 10+ authoritative sources on the topic + - Prioritize recent publications and expert opinions + - Identify key stakeholders and perspectives + + 2. Analysis Phase 📊 + - Extract and verify critical information + - Cross-reference facts across multiple sources + - Identify emerging patterns and trends + - Evaluate conflicting viewpoints + + 3. Writing Phase ✍️ + - Craft an attention-grabbing headline + - Structure content in NYT style + - Include relevant quotes and statistics + - Maintain objectivity and balance + - Explain complex concepts clearly + + 4. Quality Control ✓ + - Verify all facts and attributions + - Ensure narrative flow and readability + - Add context where necessary + - Include future implications + """), + expected_output=dedent("""\ + # {Compelling Headline} 📰 + + ## Executive Summary + {Concise overview of key findings and significance} + + ## Background & Context + {Historical context and importance} + {Current landscape overview} + + ## Key Findings + {Main discoveries and analysis} + {Expert insights and quotes} + {Statistical evidence} + + ## Impact Analysis + {Current implications} + {Stakeholder perspectives} + {Industry/societal effects} + + ## Future Outlook + {Emerging trends} + {Expert predictions} + {Potential challenges and opportunities} + + ## Expert Insights + {Notable quotes and analysis from industry leaders} + {Contrasting viewpoints} + + ## Sources & Methodology + {List of primary sources with key contributions} + {Research methodology overview} + + --- + Research conducted by AI Investigative Journalist + New York Times Style Report + Published: {current_date} + Last Updated: {current_time} + """), + markdown=True, + show_tool_calls=True, + add_datetime_to_instructions=True, +) diff --git a/frameworks/agno/research-agent/agentuity.yaml b/frameworks/agno/research-agent/agentuity.yaml new file mode 100644 index 00000000..0357e7d6 --- /dev/null +++ b/frameworks/agno/research-agent/agentuity.yaml @@ -0,0 +1,62 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/agentuity/cli/refs/heads/main/agentuity.schema.json + +# ------------------------------------------------ +# This file is generated by Agentuity +# You should check this file into version control +# ------------------------------------------------ + +# The version semver range required to run this project +version: '>=0.0.142' +# The ID of the project which is automatically generated +project_id: proj_research_agent_agno_example +# The name of the project which is editable +name: agno-research-agent +# The description of the project which is editable +description: "Agno Research Agent converted to Agentuity - performs comprehensive investigative journalism with web search and content analysis" +# The development configuration for the project +development: + # The port to run the development server on which can be overridden by setting the PORT environment variable + port: 3500 + watch: + # Whether to watch for changes and automatically restart the server + enabled: true + # Rules for files to watch for changes + files: + - agents/** + # The command to run the development server + command: uv + # The arguments to pass to the development server + args: + - run + - --env-file + - .env + - --env-file + - .env.development + - server.py +deployment: + command: uv + args: + - run + - server.py + # You should tune the resources for the deployment + resources: + # The memory requirements + memory: 512Mi + # The CPU requirements + cpu: 1000M + # The disk size requirements + disk: 500Mi +# You should not need to change these value +bundler: + enabled: true + identifier: python-uv + language: python + runtime: uv + agents: + dir: agents + ignore: + - '**/__pycache__/**' +# The agents that are part of this project +agents: + - id: agent_research_agno_example + name: ResearchAgent diff --git a/frameworks/agno/research-agent/pyproject.toml b/frameworks/agno/research-agent/pyproject.toml new file mode 100644 index 00000000..07660e17 --- /dev/null +++ b/frameworks/agno/research-agent/pyproject.toml @@ -0,0 +1,12 @@ +[project] +name = "agno-research-agent" +version = "0.1.0" +description = "Agno Research Agent wrapped for Agentuity platform" +requires-python = ">=3.10, <3.13" +dependencies = [ + "agentuity>=0.0.90", + "agno", + "duckduckgo-search", + "newspaper4k", + "lxml-html-clean", +] diff --git a/frameworks/agno/research-agent/requirements.txt b/frameworks/agno/research-agent/requirements.txt new file mode 100644 index 00000000..81c1bf86 --- /dev/null +++ b/frameworks/agno/research-agent/requirements.txt @@ -0,0 +1,4 @@ +agno +duckduckgo-search +newspaper4k +lxml-html-clean diff --git a/frameworks/agno/research-agent/server.py b/frameworks/agno/research-agent/server.py new file mode 100644 index 00000000..54e80cde --- /dev/null +++ b/frameworks/agno/research-agent/server.py @@ -0,0 +1,9 @@ +#!/usr/bin/env python3 + +import uvicorn +from agentuity.server import create_server + +app = create_server() + +if __name__ == "__main__": + uvicorn.run(app, host="0.0.0.0", port=3500) From 5825a8a145a9e8cc1a447f6baec47e286b0988ce Mon Sep 17 00:00:00 2001 From: dhilanfye34 Date: Wed, 10 Sep 2025 14:45:07 -0400 Subject: [PATCH 2/2] first changes --- .../.agentuity-crash-1756999580.json | 18 +++++++++ .../research-agent/.agentuity/config.json | 1 + .../agno/research-agent/.env.development | 1 + .../agents/ResearchAgent/__init__.py | 0 .../agno/research-agent/agents/__init__.py | 0 frameworks/agno/research-agent/agentuity.yaml | 8 ++-- frameworks/agno/research-agent/server.py | 37 +++++++++++++++++++ 7 files changed, 62 insertions(+), 3 deletions(-) create mode 100644 frameworks/agno/research-agent/.agentuity-crash-1756999580.json create mode 100644 frameworks/agno/research-agent/.agentuity/config.json create mode 100644 frameworks/agno/research-agent/.env.development create mode 100644 frameworks/agno/research-agent/agents/ResearchAgent/__init__.py create mode 100644 frameworks/agno/research-agent/agents/__init__.py diff --git a/frameworks/agno/research-agent/.agentuity-crash-1756999580.json b/frameworks/agno/research-agent/.agentuity-crash-1756999580.json new file mode 100644 index 00000000..3b88a4cd --- /dev/null +++ b/frameworks/agno/research-agent/.agentuity-crash-1756999580.json @@ -0,0 +1,18 @@ +{ + "id": "fb2343c7-b989-4468-b86e-bd22d55dae6c", + "timestamp": "2025-09-04T11:26:20-04:00", + "error": "failed to install dependencies (exit code 2): exit status 2. error: Unable to find lockfile at `uv.lock`. To create a lockfile, run `uv lock` or `uv sync`.\n", + "error_type": { + "code": "CLI-0006", + "message": "Invalid configuration" + }, + "username": "dhilanfye", + "os_name": "darwin", + "os_arch": "arm64", + "cli_version": "0.0.166", + "attributes": { + "message": "Failed to bundle project: failed to install dependencies (exit code 2): exit status 2. error: Unable to find lockfile at `uv.lock`. To create a lockfile, run `uv lock` or `uv sync`.\n", + "user_id": "user_2x3CH4tR8dMwfWSkzUsyLznYKQT" + }, + "stack_trace": "goroutine 73 [running]:\nruntime/debug.Stack()\n\t/home/runner/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.25.0.linux-amd64/src/runtime/debug/stack.go:26 +0x64\ngithub.com/agentuity/cli/internal/errsystem.(*errSystem).ShowErrorAndExit(0x14000236230)\n\t/home/runner/_work/cli/cli/internal/errsystem/console.go:103 +0x7c\ngithub.com/agentuity/cli/cmd.init.func31.2.1()\n\t/home/runner/_work/cli/cli/cmd/dev.go:168 +0x188\ngithub.com/agentuity/go-common/tui.ShowSpinner.func1()\n\t/home/runner/go/pkg/mod/github.com/agentuity/go-common@v1.0.72/tui/spinner.go:31 +0x48\ngithub.com/agentuity/go-common/tui.ShowSpinner.(*Spinner).Action.func2({0x0?, 0x0?})\n\t/home/runner/go/pkg/mod/github.com/charmbracelet/huh/spinner@v0.0.0-20250313000648-36d9de46d64e/spinner.go:74 +0x24\ngithub.com/charmbracelet/huh/spinner.(*Spinner).Init.func1()\n\t/home/runner/go/pkg/mod/github.com/charmbracelet/huh/spinner@v0.0.0-20250313000648-36d9de46d64e/spinner.go:131 +0x34\ngithub.com/charmbracelet/bubbletea.(*Program).handleCommands.func1.1()\n\t/home/runner/go/pkg/mod/github.com/charmbracelet/bubbletea@v1.3.4/tea.go:352 +0x5c\ncreated by github.com/charmbracelet/bubbletea.(*Program).handleCommands.func1 in goroutine 105\n\t/home/runner/go/pkg/mod/github.com/charmbracelet/bubbletea@v1.3.4/tea.go:346 +0xf4\n" + } diff --git a/frameworks/agno/research-agent/.agentuity/config.json b/frameworks/agno/research-agent/.agentuity/config.json new file mode 100644 index 00000000..5b476d61 --- /dev/null +++ b/frameworks/agno/research-agent/.agentuity/config.json @@ -0,0 +1 @@ +{"agents":[{"id":"agent_bbfdb1c16507278cbc24ba49019b06b4","name":"ResearchAgent","filename":"agents/ResearchAgent/agent.py"}],"app":{"name":"agno-research-agent","version":"0.1.0"},"cli_version":"0.0.166","environment":"development"} \ No newline at end of file diff --git a/frameworks/agno/research-agent/.env.development b/frameworks/agno/research-agent/.env.development new file mode 100644 index 00000000..775450c8 --- /dev/null +++ b/frameworks/agno/research-agent/.env.development @@ -0,0 +1 @@ +# This file is used to store development environment variables diff --git a/frameworks/agno/research-agent/agents/ResearchAgent/__init__.py b/frameworks/agno/research-agent/agents/ResearchAgent/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/frameworks/agno/research-agent/agents/__init__.py b/frameworks/agno/research-agent/agents/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/frameworks/agno/research-agent/agentuity.yaml b/frameworks/agno/research-agent/agentuity.yaml index 0357e7d6..c9d22aea 100644 --- a/frameworks/agno/research-agent/agentuity.yaml +++ b/frameworks/agno/research-agent/agentuity.yaml @@ -8,11 +8,11 @@ # The version semver range required to run this project version: '>=0.0.142' # The ID of the project which is automatically generated -project_id: proj_research_agent_agno_example +project_id: proj_8018c9a68c336d7d81ef3b509194b868 # The name of the project which is editable name: agno-research-agent # The description of the project which is editable -description: "Agno Research Agent converted to Agentuity - performs comprehensive investigative journalism with web search and content analysis" +description: Agno Research Agent converted to Agentuity - performs comprehensive investigative journalism with web search and content analysis # The development configuration for the project development: # The port to run the development server on which can be overridden by setting the PORT environment variable @@ -58,5 +58,7 @@ bundler: - '**/__pycache__/**' # The agents that are part of this project agents: - - id: agent_research_agno_example + - # The ID of the Agent which is automatically generated + id: agent_bbfdb1c16507278cbc24ba49019b06b4 + # The name of the Agent which is editable name: ResearchAgent diff --git a/frameworks/agno/research-agent/server.py b/frameworks/agno/research-agent/server.py index 54e80cde..984dc799 100644 --- a/frameworks/agno/research-agent/server.py +++ b/frameworks/agno/research-agent/server.py @@ -1,3 +1,40 @@ +from agentuity import autostart +import logging +import os +import sys + +if __name__ == "__main__": + # Check if AGENTUITY_API_KEY is set + if not os.environ.get("AGENTUITY_API_KEY") and not os.environ.get( + "AGENTUITY_SDK_KEY" + ): + print( + "\033[31m[ERROR] AGENTUITY_API_KEY or AGENTUITY_SDK_KEY is not set. This should have been set automatically by the Agentuity CLI or picked up from the .env file.\033[0m" + ) + if os.environ.get("_", "").endswith("uv") and os.path.exists(".env"): + print( + "\033[31m[ERROR] Re-run the command with `uv run --env-file .env server.py`\033[0m" + ) + sys.exit(1) + + # Check if AGENTUITY_URL is set + if not os.environ.get("AGENTUITY_URL"): + print( + "\033[31m[WARN] You are running this agent outside of the Agentuity environment. Any automatic Agentuity features will be disabled.\033[0m" + ) + print( + "\033[31m[WARN] Recommend running `agentuity dev` to run your project locally instead of `python script`.\033[0m" + ) + + # Setup logging after environment checks + logging.basicConfig( + stream=sys.stdout, + level=logging.INFO, + format="[%(levelname)-5.5s] %(message)s", + ) + + autostart() + #!/usr/bin/env python3 import uvicorn