diff --git a/devops_agent/cli.py b/devops_agent/cli.py index 3b31b20..816656d 100644 --- a/devops_agent/cli.py +++ b/devops_agent/cli.py @@ -1,8 +1,11 @@ +from pathlib import Path + import click from rich.console import Console from rich.panel import Panel from rich.prompt import Prompt from devops_agent.core.master_agent import execute_master_agent +from devops_agent.core.log_analysis_agent import execute_log_analysis_agent console = Console() @@ -52,7 +55,20 @@ def run(log_file, provider, query, output, format, interactive): if log_file: console.print(f"[yellow]Analyzing log file:[/yellow] {log_file}") - console.print("[green]✓[/green] Log analysis will be implemented here") + try: + file_path = Path(__file__).parent.joinpath(log_file) + response = execute_log_analysis_agent(provider=provider, log_file=file_path) + console.print(Panel.fit( + f"[bold yellow]Assistant:[/bold yellow] [dim]{response}[/dim]", + border_style="yellow" + )) + + if output: + save_to_file(output, query, response, format) + console.print(f"\n[dim]Response saved to {output}[/dim]") + + except Exception as e: + console.print(f"\n[red]Error:[/red] {str(e)}") if query: process_query(provider, query, output, format) diff --git a/devops_agent/core/log_analysis_agent.py b/devops_agent/core/log_analysis_agent.py new file mode 100644 index 0000000..5fb9a4a --- /dev/null +++ b/devops_agent/core/log_analysis_agent.py @@ -0,0 +1,44 @@ +import os +from pathlib import Path + +from agno.agent import Agent +from agno.media import File +from agno.models.openai import OpenAIChat +from agno.models.anthropic import Claude +from agno.models.google.gemini import Gemini +from rich.console import Console +from rich.panel import Panel + +console = Console() + +def execute_log_analysis_agent(provider: str, log_file: Path) -> Agent: + console.print(Panel.fit( + "[bold cyan]Log Analysis Agent Invoking...[/bold cyan]", + border_style="cyan" + )) + llm_provider = provider.lower().strip() + if llm_provider == 'openai': + model = OpenAIChat(id="gpt-5-mini", api_key=os.environ.get('OPENAI_API_KEY')) + elif llm_provider == 'anthropic': + model = Claude(id="claude-sonnet-4-5-20250929", temperature=0.6, api_key=os.environ.get('ANTHROPIC_API_KEY')) + elif llm_provider == 'google': + model = Gemini(id="gemini-2.5-flash", temperature=0.6, api_key=os.environ.get('GEMINI_API_KEY')) + else: + model = OpenAIChat(id="gpt-5-mini"), #default + + file_analysis_agent = Agent( + name="LogFile Analysis Agent", + role="Analyze log files", + model=model, + description="You are an AI agent that can analyze log files.", + instructions=[ + "You are an AI agent that can analyze log files.", + "You are given a log file and you need to analyse and give detailed answer to the question from the user.", + ], + ) + + print("executing the log analysis") + user_query = 'analyse and give all the insights such as critical errors, patterns, anomalies, or any other significant findings' + response = file_analysis_agent.run(user_query, files=[File(filepath=log_file)]) + + return response.content \ No newline at end of file diff --git a/devops_agent/core/master_agent.py b/devops_agent/core/master_agent.py index 6cd5800..aabe44e 100644 --- a/devops_agent/core/master_agent.py +++ b/devops_agent/core/master_agent.py @@ -1,5 +1,6 @@ import asyncio import os +from pathlib import Path from typing import Any from agno.knowledge import Knowledge @@ -16,12 +17,9 @@ from devops_agent.core.devops_agent import execute_devops_agent from devops_agent.core.kubernetes_agent import execute_k8s_agent +from devops_agent.core.terraform_agent import execute_terraform_agent from rich.console import Console -from rich.panel import Panel -from rich.live import Live -from rich.markdown import Markdown -from rich.console import Group from dotenv import load_dotenv, find_dotenv @@ -42,7 +40,7 @@ knowledge = Knowledge(vector_db=vector_db) -def execute_master_agent(provider: str, user_query: str) -> str: +def execute_master_agent(provider: str, user_query: str = None, log_file: Path = None) -> str: llm_provider = provider.lower().strip() if llm_provider == 'openai': model = OpenAIChat(id="gpt-5-mini", api_key=os.environ.get('OPENAI_API_KEY')) @@ -59,18 +57,19 @@ def execute_master_agent(provider: str, user_query: str) -> str: members=[ execute_devops_agent(provider=provider), execute_k8s_agent(provider=provider), + execute_terraform_agent(provider=provider) ], instructions=[ "You are a intelligent router that directs questions to the appropriate agent.", "If the user asks in a non devops or k8s question whose agent is not a team member, respond in English with:", - "'I can only answer in the following technologies: Devops & Kubernetes Architecture on Multiple clouds. Please ask your question in one of these technologies.'", + "'I can only answer in the following technologies: Devops, terraform & Kubernetes Architecture on Multiple clouds. Please ask your question in one of these technologies.'", "Always check the technology or domain of the user's input before routing to an agent.", "For unsupported technologies like coding, flowcharts, analytics etc respond in English with the above message.", ], tools=[ReasoningTools()], # Enable reasoning capabilities knowledge=knowledge, db=InMemoryDb(), - respond_directly=False, # if set to true the member response if directly given to user + respond_directly=True, # if set to true the member response is directly given to user determine_input_for_members=False, delegate_task_to_all_members=False, stream_intermediate_steps=True, @@ -82,7 +81,6 @@ def execute_master_agent(provider: str, user_query: str) -> str: enable_agentic_memory=True, markdown=True ) - response = devops_team.run(user_query, stream_intermediate_steps=True, retry=3) # saved the response to knowledge in async mode diff --git a/devops_agent/core/terraform_agent.py b/devops_agent/core/terraform_agent.py new file mode 100644 index 0000000..0a84622 --- /dev/null +++ b/devops_agent/core/terraform_agent.py @@ -0,0 +1,43 @@ +import asyncio +import os + +from agno.agent import Agent +from agno.models.openai import OpenAIChat +from agno.models.anthropic import Claude +from agno.models.google.gemini import Gemini +from rich.console import Console +from rich.panel import Panel + +from devops_agent.utils.prompt_generator_from_poml import prompt_from_poml + +terraform_prompt = prompt_from_poml('terraform.poml') + +console = Console() + +def execute_terraform_agent(provider: str, user_query: str = None) -> Agent: + + console.print(Panel.fit( + "[bold cyan]Terraform Agent Invoking...[/bold cyan]", + border_style="cyan" + )) + + llm_provider = provider.lower().strip() + if llm_provider == 'openai': + model = OpenAIChat(id="gpt-5-mini", api_key=os.environ.get('OPENAI_API_KEY')) + elif llm_provider == 'anthropic': + model = Claude(id="claude-sonnet-4-5-20250929", temperature=0.6, api_key=os.environ.get('ANTHROPIC_API_KEY')) + elif llm_provider == 'google': + model = Gemini(id="gemini-2.5-flash", temperature=0.6, api_key=os.environ.get('GEMINI_API_KEY')) + else: + model = OpenAIChat(id="gpt-5-mini"), # default + + terraform_assist = Agent( + name="Kubernetes Agent", + model=model, + description="You help answer questions about the terraform technology with respect to platforms like Azure, AWS, and GCP. Always ask the cloud provider if not provided in the user_query before proceeding.", + instructions=terraform_prompt, + stream_intermediate_steps=True, + markdown=True, + ) + + return terraform_assist diff --git a/devops_agent/playground.py b/devops_agent/playground.py deleted file mode 100644 index 41c4c15..0000000 --- a/devops_agent/playground.py +++ /dev/null @@ -1,7 +0,0 @@ -from devops_agent.core.master_agent import execute_master_agent -from dotenv import load_dotenv, find_dotenv - -load_dotenv(find_dotenv()) - -if __name__ == '__main__': - execute_master_agent(provider="openai", user_query="Analyze distributed tracing data to identify performance bottleneck in microservices architecture") \ No newline at end of file