{"id":26057582,"url":"https://github.com/frostlogic-ab/agent-forge","last_synced_at":"2025-07-22T14:02:59.941Z","repository":{"id":281165424,"uuid":"944434504","full_name":"frostlogic-ab/agent-forge","owner":"frostlogic-ab","description":"Agent Forge is a TypeScript framework for creating, configuring, and orchestrating AI agents that connect to LLMs (Large Language Models)","archived":false,"fork":false,"pushed_at":"2025-07-08T20:08:58.000Z","size":26183,"stargazers_count":13,"open_issues_count":0,"forks_count":5,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-07-22T14:02:52.246Z","etag":null,"topics":["agents","ai","framework","llm","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/frostlogic-ab.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-03-07T10:40:05.000Z","updated_at":"2025-07-08T20:09:01.000Z","dependencies_parsed_at":null,"dependency_job_id":"e2ca2b99-3280-4f0f-be10-48a8debf703c","html_url":"https://github.com/frostlogic-ab/agent-forge","commit_stats":null,"previous_names":["frostlogic-ab/agent-forge"],"tags_count":56,"template":false,"template_full_name":null,"purl":"pkg:github/frostlogic-ab/agent-forge","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/frostlogic-ab%2Fagent-forge","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/frostlogic-ab%2Fagent-forge/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/frostlogic-ab%2Fagent-forge/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/frostlogic-ab%2Fagent-forge/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/frostlogic-ab","download_url":"https://codeload.github.com/frostlogic-ab/agent-forge/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/frostlogic-ab%2Fagent-forge/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266507366,"owners_count":23940055,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-22T02:00:09.085Z","response_time":66,"last_error":null,"robots_txt_status":null,"robots_txt_updated_at":null,"robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["agents","ai","framework","llm","typescript"],"created_at":"2025-03-08T11:49:44.811Z","updated_at":"2025-07-22T14:02:59.910Z","avatar_url":"https://github.com/frostlogic-ab.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Agent Forge 🔨\n\n[![TypeScript](https://img.shields.io/badge/TypeScript-007ACC?style=for-the-badge\u0026logo=typescript\u0026logoColor=white)](https://www.typescriptlang.org/)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg?style=for-the-badge)](https://opensource.org/licenses/MIT)\n[![Documentation](https://img.shields.io/badge/Documentation-blue?style=for-the-badge\u0026logo=read-the-docs\u0026logoColor=white)](https://frostlogic-ab.github.io/agent-forge/)\n\nAgent Forge is a TypeScript framework for building, orchestrating, and running advanced AI agents and agent teams. It supports LLMs, tool use, hierarchical teams, remote agent protocols (A2A), and MCP tool integration. Designed for extensibility, composability, and real-world AI agent applications.\n\n## Features\n\n- **Decorator-based agent definition**: Use TypeScript decorators for agent config, LLM provider, tool integration, and remote protocols.\n- **Tool ecosystem**: Add built-in, custom, or MCP tools to agents.\n- **Teams**: Create hierarchical teams with a manager agent that delegates tasks.\n- **Remote agents (A2A)**: Expose agents as remote services or connect to remote agents.\n- **Streaming**: Real-time streaming of LLM and agent outputs.\n- **TypeScript-first**: Full type safety and modern developer experience.\n\n## Installation\n\n```bash\nyarn add agent-forge\n# or\nnpm install agent-forge\n```\n\n### TypeScript Configuration\n\nAgent Forge uses TypeScript decorators extensively. You **must** enable decorator support in your `tsconfig.json` file for the framework to work properly.\n\nAdd these options to your `tsconfig.json`:\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true\n    // ... other options\n  }\n}\n```\n\n### Example tsconfig.json\n\nHere's a minimal `tsconfig.json` that works with Agent Forge:\n\n```json\n{\n  \"compilerOptions\": {\n    \"target\": \"es2020\",\n    \"module\": \"commonjs\",\n    \"lib\": [\"es2020\"],\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true,\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true,\n    \"forceConsistentCasingInFileNames\": true,\n    \"declaration\": true,\n    \"outDir\": \"./dist\",\n    \"rootDir\": \"./src\"\n  },\n  \"include\": [\"src/**/*\"],\n  \"exclude\": [\"node_modules\", \"dist\"]\n}\n```\n\n**Prerequisites:**\n\n- Node.js (latest LTS recommended)\n- LLM API keys (e.g., OpenAI)\n\n## Quick Start\n\n### 1. Team of Local Agents\n\n```ts\nimport { forge, llmProvider, agent, readyForge } from \"agent-forge\";\nimport { AgentForge, Agent } from \"agent-forge\";\n\n@agent({\n  name: \"ManagerAgent\",\n  role: \"Manager\",\n  description: \"Delegates tasks to team members.\",\n  objective: \"Coordinate the team to solve complex tasks.\",\n  model: process.env.LLM_API_MODEL!,\n})\nclass ManagerAgent extends Agent {}\n\n@agent({\n  name: \"ResearcherAgent\",\n  role: \"Research Specialist\",\n  description: \"Finds and analyzes information.\",\n  objective: \"Provide accurate, relevant information.\",\n  model: process.env.LLM_API_MODEL!,\n})\nclass ResearcherAgent extends Agent {}\n\n@agent({\n  name: \"SummarizerAgent\",\n  role: \"Summarizer\",\n  description: \"Summarizes information.\",\n  objective: \"Create concise summaries.\",\n  model: process.env.LLM_API_MODEL!,\n})\nclass SummarizerAgent extends Agent {}\n\n@llmProvider(\"openai\", { apiKey: process.env.LLM_API_KEY })\n@forge()\nclass TeamExample {\n  static forge: AgentForge;\n\n  static async run() {\n    // Pass agent classes to readyForge - it will handle instantiation\n    const agentClasses = [ManagerAgent, ResearcherAgent, SummarizerAgent];\n    await readyForge(TeamExample, agentClasses);\n\n    const team = TeamExample.forge\n      .createTeam(\n        \"ManagerAgent\",\n        \"Team\",\n        \"A team of agents that can help with a variety of tasks.\"\n      )\n      .addAgent(TeamExample.forge.getAgent(\"ResearcherAgent\")!)\n      .addAgent(TeamExample.forge.getAgent(\"SummarizerAgent\")!);\n    const result = await team.run(\n      \"What is the status of AI in 2025? Make a full report and summary.\",\n      { verbose: true }\n    );\n    console.log(result.output);\n  }\n}\n\nTeamExample.run();\n```\n\n## Logging Configuration\n\nAgent Forge provides comprehensive logging capabilities with configurable levels. You can control logging behavior at the decorator level for fine-grained control:\n\n### Basic Logging Configuration\n\n```ts\nimport { forge, llmProvider, LogLevel } from \"agent-forge\";\n\n@llmProvider(\"openai\", { apiKey: process.env.OPENAI_API_KEY })\n@forge({\n  logger: {\n    level: LogLevel.DEBUG,  // Enable debug logging\n    enableConsoleLogging: true,\n    enablePerformanceLogging: true\n  }\n})\nclass MyApplication {\n  static forge: AgentForge;\n}\n```\n\n### Available Log Levels\n\n- **`LogLevel.DEBUG`** (0) - Most verbose, shows everything including LLM interactions\n- **`LogLevel.INFO`** (1) - Default level, shows info, warnings, errors, critical  \n- **`LogLevel.WARNING`** (2) - Shows warnings, errors, critical\n- **`LogLevel.ERROR`** (3) - Shows only errors and critical issues\n- **`LogLevel.CRITICAL`** (4) - Shows only critical errors\n\n### Logger Configuration Options\n\n```ts\ninterface ForgeConfig {\n  logger?: {\n    level: LogLevel;                 // Logging level\n    enableConsoleLogging: boolean;   // Console output\n    enableEventEmission: boolean;    // Event emission\n    enablePerformanceLogging: boolean; // Performance tracking\n    enableErrorAggregation: boolean; // Error counting\n    maxLogHistory: number;           // Log history size\n  };\n}\n```\n\n### Environment-Specific Examples\n\n```ts\n// Development: Debug everything\n@forge({\n  logger: {\n    level: LogLevel.DEBUG,\n    enableConsoleLogging: true,\n    enablePerformanceLogging: true,\n    enableErrorAggregation: true,\n    maxLogHistory: 1000\n  }\n})\nclass DevEnvironment {}\n\n// Production: Errors only\n@forge({\n  logger: {\n    level: LogLevel.ERROR,\n    enableConsoleLogging: true,\n    enablePerformanceLogging: false,\n    enableErrorAggregation: true,\n    maxLogHistory: 100\n  }\n})\nclass ProductionEnvironment {}\n\n// Default behavior (no config needed)\n@forge() // Uses LogLevel.INFO with default settings\n```\n\n### 2. Workflows: Step-by-Step Task Automation\n\nAgent Forge supports workflows, allowing you to define a sequence of agent steps for complex, multi-stage tasks. Workflows are ideal when you want to chain agent outputs, such as research followed by summarization.\n\n```ts\nimport { forge, llmProvider, agent, readyForge, LogLevel } from \"agent-forge\";\nimport { AgentForge, Agent, LLMProvider } from \"agent-forge\";\nimport * as dotenv from \"dotenv\";\n\ndotenv.config();\n\n@agent({\n  name: \"Researcher\",\n  role: \"Research Specialist\",\n  description: \"A specialized agent for gathering and analyzing information.\",\n  objective: \"Find accurate and relevant information on requested topics.\",\n  model: process.env.LLM_API_MODEL!,\n  temperature: 0.4,\n})\nclass ResearcherAgent extends Agent {}\n\n@agent({\n  name: \"Summarizer\",\n  role: \"Concise Summarizer\",\n  description:\n    \"An agent that specializes in distilling information into clear summaries.\",\n  objective: \"Create concise, accurate summaries of complex information.\",\n  model: process.env.LLM_API_MODEL!,\n  temperature: 0.4,\n})\nclass SummarizerAgent extends Agent {}\n\n@llmProvider(process.env.LLM_PROVIDER as LLMProvider, {\n  apiKey: process.env.LLM_API_KEY,\n})\n@forge({\n  logger: {\n    level: LogLevel.INFO,  // Balanced logging for workflow tracking\n    enablePerformanceLogging: true\n  }\n})\nclass WorkflowExample {\n  static forge: AgentForge;\n\n  static async run() {\n    const agentClasses = [ResearcherAgent, SummarizerAgent];\n    await readyForge(WorkflowExample, agentClasses);\n\n    // Create a workflow: research, then summarize\n    const workflow = WorkflowExample.forge.createWorkflow(\n      \"Research and Summarize\",\n      \"Research a topic and then summarize the findings\"\n    );\n    workflow.addStep(WorkflowExample.forge.getAgent(\"Researcher\")!); // Researcher\n    workflow.addStep(WorkflowExample.forge.getAgent(\"Summarizer\")!); // Summarizer\n\n    const result = await workflow.run(\n      \"What is quantum computing and how might it affect cybersecurity?\",\n      { verbose: true }\n    );\n    console.log(\"Workflow Result:\", result.output);\n  }\n}\n\nWorkflowExample.run();\n```\n\n**What this does:**\n\n- Defines two agents: a Researcher and a Summarizer.\n- Registers them with the forge instance.\n- Creates a workflow where the Researcher investigates a topic, and the Summarizer condenses the findings.\n- Runs the workflow on a sample question and prints the result.\n\n### 3. Expose an Agent as a Remote A2A Server\n\n```ts\nimport { a2aServer, agent, llmProvider } from \"agent-forge\";\nimport { Agent } from \"agent-forge\";\n\n@llmProvider(\"openai\", { apiKey: process.env.LLM_API_KEY })\n@a2aServer({ port: 41241, host: \"localhost\", endpoint: \"/a2a\", verbose: true })\n@agent({\n  name: \"HelpfulAssistantAgent\",\n  role: \"Helpful Assistant\",\n  description: \"An AI assistant that tries to be helpful, hosted via A2A.\",\n  objective: \"To answer questions and perform tasks as a helpful AI assistant.\",\n  model: process.env.LLM_API_MODEL!,\n})\nexport class HelpfulAssistantAgent extends Agent {}\n\nnew HelpfulAssistantAgent();\nconsole.log(\"A2A server started. Press Ctrl+C to stop.\");\n```\n\n### 4. Connect to a Remote Agent (A2A Client)\n\n```ts\nimport { a2aClient } from \"agent-forge\";\nimport { Agent } from \"agent-forge\";\n\n@a2aClient({ serverUrl: \"http://localhost:41241/a2a\" })\nexport class RemoteHelpfulAssistant extends Agent {}\n\n(async () =\u003e {\n  const remoteAgent = await new RemoteHelpfulAssistant();\n  const result = await remoteAgent.run(\"Summarize the latest AI trends.\");\n  console.log(result.output);\n})();\n```\n\n### 5. Team with a Remote Agent as a Member\n\n```ts\nimport { forge, llmProvider, agent, a2aClient } from \"agent-forge\";\nimport { AgentForge, Agent } from \"agent-forge\";\n\n@agent({\n  name: \"ManagerAgent\",\n  role: \"Manager\",\n  description: \"Delegates tasks to team members.\",\n  objective: \"Coordinate the team to solve complex tasks.\",\n  model: process.env.LLM_API_MODEL!,\n})\nclass ManagerAgent extends Agent {}\n\n@agent({\n  name: \"SummarizerAgent\",\n  role: \"Summarizer\",\n  description: \"Summarizes information.\",\n  objective: \"Create concise summaries.\",\n  model: process.env.LLM_API_MODEL!,\n})\nclass SummarizerAgent extends Agent {}\n\n@a2aClient({ serverUrl: \"http://localhost:41241/a2a\" })\nclass RemoteHelpfulAssistant extends Agent {}\n\n@llmProvider(\"openai\", { apiKey: process.env.LLM_API_KEY })\n@forge()\nclass TeamWithRemoteExample {\n  static forge: AgentForge;\n\n  static async run() {\n    // Pass both local and remote agent classes to readyForge\n    const agentClasses = [\n      ManagerAgent,\n      SummarizerAgent,\n      RemoteHelpfulAssistant,\n    ];\n    await readyForge(TeamWithRemoteExample, agentClasses);\n\n    const team = TeamWithRemoteExample.forge\n      .createTeam(\"ManagerAgent\", \"Hybrid Team\", \"A team with a remote agent\")\n      .addAgent(TeamWithRemoteExample.forge.getAgent(\"SummarizerAgent\")!)\n      .addAgent(\n        TeamWithRemoteExample.forge.getAgent(\"RemoteHelpfulAssistant\")!\n      );\n    const result = await team.run(\n      \"What are the most important AI trends in 2025? Summarize the findings.\",\n      { verbose: true }\n    );\n    console.log(result.output);\n  }\n}\n\nTeamWithRemoteExample.run();\n```\n\n### 5. Using Tools with Agents\n\nAgent Forge provides a powerful tool system that allows agents to interact with external systems, APIs, and services. Tools can be added to agents using the `@tool` decorator.\n\n#### Adding Tools with the `@tool` Decorator\n\n```ts\nimport { agent, tool, llmProvider, forge } from \"agent-forge\";\nimport {\n  Agent,\n  AgentForge,\n  WebSearchTool,\n  WebPageContentTool,\n} from \"agent-forge\";\n\n@tool(WebSearchTool)\n@tool(WebPageContentTool)\n@agent({\n  name: \"ResearchAgent\",\n  role: \"Research Assistant\",\n  description:\n    \"An agent that can search the web and extract content from pages.\",\n  objective: \"Help users find and analyze information from the web.\",\n  model: process.env.LLM_API_MODEL!,\n  temperature: 0.7,\n})\nclass ResearchAgent extends Agent {}\n\n@llmProvider(\"openai\", { apiKey: process.env.LLM_API_KEY })\n@forge()\nclass ToolExample {\n  static forge: AgentForge;\n\n  static async run() {\n    const agentClasses = [ResearchAgent];\n    await readyForge(ToolExample, agentClasses);\n\n    const result = await ToolExample.forge.runAgent(\n      \"ResearchAgent\",\n      \"Search for the latest developments in quantum computing and summarize the findings\"\n    );\n    console.log(result.output);\n  }\n}\n\nToolExample.run();\n```\n\n#### Creating Custom Tools\n\nYou can create custom tools by extending the `Tool` base class:\n\n```ts\nimport { Tool } from \"agent-forge\";\nimport { ToolParameter } from \"agent-forge\";\n\nclass CalculatorTool extends Tool {\n  constructor() {\n    const parameters: ToolParameter[] = [\n      {\n        name: \"expression\",\n        type: \"string\",\n        description: \"The mathematical expression to evaluate\",\n        required: true,\n      },\n    ];\n\n    super(\n      \"Calculator\",\n      \"Evaluate mathematical expressions\",\n      parameters,\n      \"The result of the evaluated expression\"\n    );\n  }\n\n  protected async run(params: { expression: string }): Promise\u003cany\u003e {\n    try {\n      // Note: In production, use a proper math parser instead of eval\n      const result = eval(params.expression);\n      return { result, expression: params.expression };\n    } catch (error) {\n      return {\n        error: `Failed to evaluate expression: ${\n          error instanceof Error ? error.message : String(error)\n        }`,\n      };\n    }\n  }\n}\n\nclass WeatherTool extends Tool {\n  constructor() {\n    const parameters: ToolParameter[] = [\n      {\n        name: \"location\",\n        type: \"string\",\n        description: \"The location to get weather for\",\n        required: true,\n      },\n      {\n        name: \"units\",\n        type: \"string\",\n        description: \"Temperature units (celsius or fahrenheit)\",\n        required: false,\n        default: \"celsius\",\n      },\n    ];\n\n    super(\n      \"Weather\",\n      \"Get current weather information for a location\",\n      parameters,\n      \"Weather information including temperature, conditions, and forecast\"\n    );\n  }\n\n  protected async run(params: {\n    location: string;\n    units?: string;\n  }): Promise\u003cany\u003e {\n    // This is a mock implementation. In production, call a real weather API\n    const { location, units = \"celsius\" } = params;\n\n    return {\n      location,\n      temperature: units === \"celsius\" ? \"22°C\" : \"72°F\",\n      conditions: \"Partly cloudy\",\n      forecast: \"Sunny tomorrow\",\n      humidity: \"65%\",\n      windSpeed: \"10 km/h\",\n    };\n  }\n}\n\n// Use the custom tools with an agent\n@tool(CalculatorTool)\n@tool(WeatherTool)\n@agent({\n  name: \"Assistant\",\n  role: \"General Assistant\",\n  description: \"A helpful assistant with calculator and weather capabilities.\",\n  objective: \"Help users with calculations and weather information.\",\n  model: process.env.LLM_API_MODEL!,\n  temperature: 0.7,\n})\nclass AssistantAgent extends Agent {}\n```\n\n#### Tool Requirements\n\nWhen creating custom tools, follow these guidelines:\n\n1. **Extend the Tool base class**: Your tool must inherit from `Tool`\n2. **Define parameters**: Specify what parameters your tool accepts using `ToolParameter[]`\n3. **Implement the `run` method**: This is where your tool's logic goes\n4. **Handle errors gracefully**: Return error information instead of throwing when possible\n5. **Return structured data**: Return objects that the LLM can easily understand and use\n\n#### Tool Parameter Types\n\nSupported parameter types:\n\n- `string`: Text input\n- `number`: Numeric input\n- `boolean`: True/false values\n- `array`: List of values\n- `object`: Structured data\n\n```ts\nconst parameters: ToolParameter[] = [\n  {\n    name: \"query\",\n    type: \"string\",\n    description: \"The search query\",\n    required: true,\n  },\n  {\n    name: \"maxResults\",\n    type: \"number\",\n    description: \"Maximum number of results to return\",\n    required: false,\n    default: 10,\n  },\n  {\n    name: \"includeImages\",\n    type: \"boolean\",\n    description: \"Whether to include images in results\",\n    required: false,\n    default: false,\n  },\n];\n```\n\n### 6. Team with MCP Tool Agent\n\n```ts\nimport { agent, llmProvider, forge, MCP, RateLimiter } from \"agent-forge\";\nimport { Agent, AgentForge } from \"agent-forge\";\nimport { MCPProtocolType } from \"agent-forge/tools/mcp-tool\";\n\n@RateLimiter({\n  rateLimitPerSecond: 1,\n  toolSpecificLimits: {\n    brave: { rateLimitPerSecond: 1 },\n  },\n  verbose: true,\n})\n@MCP(MCPProtocolType.STDIO, {\n  command: \"docker\",\n  args: [\"run\", \"-i\", \"--rm\", \"-e\", \"BRAVE_API_KEY\", \"mcp/brave-search\"],\n  env: {\n    BRAVE_API_KEY: process.env.BRAVE_API_KEY || \"\",\n  },\n  verbose: true,\n})\n@llmProvider(\"openai\", { apiKey: process.env.LLM_API_KEY })\n@agent({\n  name: \"ResearcherAgent\",\n  role: \"Research Specialist\",\n  description: \"Finds and analyzes information using Brave Search.\",\n  objective: \"Provide accurate, up-to-date information using tools.\",\n  model: process.env.LLM_API_MODEL!,\n  temperature: 0.2,\n})\nclass ResearcherAgent extends Agent {}\n\n@agent({\n  name: \"SummarizerAgent\",\n  role: \"Summarizer\",\n  description: \"Summarizes research findings.\",\n  objective: \"Create concise summaries of research results.\",\n  model: process.env.LLM_API_MODEL!,\n  temperature: 0.4,\n})\nclass SummarizerAgent extends Agent {}\n\n@agent({\n  name: \"ManagerAgent\",\n  role: \"Manager\",\n  description: \"Delegates tasks to team members.\",\n  objective: \"Coordinate the team to solve complex tasks.\",\n  model: process.env.LLM_API_MODEL!,\n  temperature: 0.7,\n})\nclass ManagerAgent extends Agent {}\n\n@llmProvider(\"openai\", { apiKey: process.env.LLM_API_KEY })\n@forge()\nclass TeamWithMCPExample {\n  static forge: AgentForge;\n\n  static async run() {\n    const agentClasses = [ManagerAgent, ResearcherAgent, SummarizerAgent];\n    await readyForge(TeamWithMCPExample, agentClasses);\n\n    const team = TeamWithMCPExample.forge\n      .createTeam(\n        \"ManagerAgent\",\n        \"Research Team\",\n        \"A team with MCP-powered research\"\n      )\n      .addAgent(TeamWithMCPExample.forge.getAgent(\"ResearcherAgent\")!)\n      .addAgent(TeamWithMCPExample.forge.getAgent(\"SummarizerAgent\")!);\n    const result = await team.run(\n      \"What are the latest breakthroughs in quantum computing? Summarize the findings.\",\n      { verbose: true }\n    );\n    console.log(result.output);\n  }\n}\n\nTeamWithMCPExample.run();\n```\n\n### 7. RAG (Retrieval-Augmented Generation) with ChromaDB\n\nAgent Forge provides built-in RAG capabilities using ChromaDB, allowing agents to retrieve and use information from indexed documents. This enables agents to answer questions based on your specific knowledge base.\n\n#### Prerequisites\n\n1. **ChromaDB Server**: Start ChromaDB using Docker:\n\n   ```bash\n   docker run -p 8000:8000 chromadb/chroma\n   ```\n\n2. **Install Dependencies**: ChromaDB is automatically included when you install Agent Forge.\n\n#### Setting Up RAG\n\n##### 1. Index Your Documents\n\nFirst, create and index your documents using the `DocumentIndexer`:\n\n```ts\nimport { DocumentIndexer, RAGChromaDbConfig } from \"agent-forge\";\n\nconst ragConfig: RAGChromaDbConfig = {\n  collectionName: \"company_knowledge_base\",\n  chromaUrl: \"http://localhost:8000\",\n  chunkSize: 800,\n  chunkOverlap: 150,\n};\n\nconst indexer = new DocumentIndexer(ragConfig);\nawait indexer.initialize();\n\n// Index a directory of documents\nconst result = await indexer.indexDirectory(\"./documents\");\nconsole.log(`Indexed ${result.documentsProcessed} documents`);\n\n// Or index specific files\nawait indexer.indexFiles([\"./file1.txt\", \"./file2.md\"]);\n\n// Or index text directly\nawait indexer.indexText(\"Your content here\", \"source-name\");\n```\n\n**Supported file types:**\n\n- `.txt` - Plain text files\n- `.md`, `.markdown` - Markdown files\n- `.json` - JSON files (text content extracted recursively)\n\n##### 2. Create RAG-Enabled Agents\n\nUse the `@RAGChromaDb` decorator to add retrieval capabilities to agents:\n\n```ts\nimport {\n  RAGChromaDb,\n  agent,\n  llmProvider,\n  forge,\n  readyForge,\n} from \"agent-forge\";\nimport { Agent, AgentForge, LLMProvider } from \"agent-forge\";\n\n@RAGChromaDb({\n  collectionName: \"company_knowledge_base\",\n  chromaUrl: \"http://localhost:8000\",\n  topK: 3,\n  similarityThreshold: 0.3,\n})\n@agent({\n  name: \"Knowledge Assistant\",\n  role: \"Knowledge Base Specialist\",\n  description: \"Assistant with access to company knowledge base\",\n  objective: \"Provide accurate information from company documents\",\n  model: process.env.LLM_API_MODEL!,\n  temperature: 0.3,\n})\nclass KnowledgeAssistant extends Agent {}\n\n@llmProvider(process.env.LLM_PROVIDER as LLMProvider, {\n  apiKey: process.env.LLM_API_KEY,\n})\n@forge()\nclass RAGExample {\n  static forge: AgentForge;\n\n  static async run() {\n    const agentClasses = [KnowledgeAssistant];\n    // readyForge automatically initializes RAG systems\n    await readyForge(RAGExample, agentClasses);\n\n    const result = await RAGExample.forge.runAgent(\n      \"Knowledge Assistant\",\n      \"What is our company's remote work policy?\"\n    );\n\n    console.log(result.output);\n  }\n}\n\nRAGExample.run();\n```\n\n##### 3. RAG Teams and Workflows\n\nRAG-enabled agents work seamlessly with teams and workflows:\n\n```ts\n@RAGChromaDb({\n  collectionName: \"company_knowledge_base\",\n  chromaUrl: \"http://localhost:8000\",\n  topK: 5,\n  similarityThreshold: 0.2,\n})\n@agent({\n  name: \"Research Specialist\",\n  role: \"Research and Analysis Expert\",\n  description: \"Specialist in researching company documents\",\n  objective: \"Conduct thorough research and analysis\",\n  model: process.env.LLM_API_MODEL!,\n  temperature: 0.4,\n})\nclass ResearchSpecialist extends Agent {}\n\n@agent({\n  name: \"Team Manager\",\n  role: \"Team Coordination Manager\",\n  description: \"Manages team workflow and coordinates responses\",\n  objective: \"Coordinate team members and synthesize expertise\",\n  model: process.env.LLM_API_MODEL!,\n  temperature: 0.6,\n})\nclass TeamManager extends Agent {}\n\n@llmProvider(process.env.LLM_PROVIDER as LLMProvider, {\n  apiKey: process.env.LLM_API_KEY,\n})\n@forge()\nclass RAGTeam {\n  static forge: AgentForge;\n\n  static async run() {\n    const agentClasses = [TeamManager, ResearchSpecialist];\n    await readyForge(RAGTeam, agentClasses);\n\n    const team = RAGTeam.forge.createTeam(\n      \"Team Manager\",\n      \"Knowledge Team\",\n      \"Team with access to company knowledge base\"\n    );\n    team.addAgent(RAGTeam.forge.getAgent(\"Research Specialist\")!);\n\n    const result = await team.run(\n      \"Research our vacation policies and technical documentation standards\",\n      { verbose: true }\n    );\n\n    console.log(result.output);\n  }\n}\n\nRAGTeam.run();\n```\n\n#### RAG Configuration Options\n\nThe `@RAGChromaDb` decorator accepts the following configuration:\n\n```ts\ninterface RAGChromaDbConfig {\n  collectionName: string; // ChromaDB collection name\n  chromaUrl?: string; // ChromaDB server URL (default: \"http://localhost:8000\")\n  topK?: number; // Number of documents to retrieve (default: 5)\n  similarityThreshold?: number; // Minimum similarity score (default: 0.0)\n  chunkSize?: number; // Text chunk size for indexing (default: 1000)\n  chunkOverlap?: number; // Chunk overlap size (default: 200)\n  maxRetries?: number; // Connection retry attempts (default: 3)\n  timeout?: number; // Request timeout in ms (default: 30000)\n}\n```\n\n#### Document Training Script\n\nYou can run the included document training example:\n\n```bash\n# Train documents (index them into ChromaDB)\nnpm run example:rag-train\n\n# Train documents with increased memory (for large document sets)\nnpm run example:rag-train-memory\n\n# Run simple RAG example\nnpm run example:rag-simple\n\n# Run RAG team example\nnpm run example:rag-team\n```\n\n**Troubleshooting Memory Issues:**\n\nIf you encounter \"heap out of memory\" errors: 2. Reduce document chunk size in your configuration 3. Process smaller batches of files at a time 4. Ensure you have sufficient system memory available\n\n#### RAG vs Non-RAG Comparison\n\nRAG-enabled agents have access to your specific knowledge base, while regular agents rely only on their training data:\n\n```ts\n// RAG-enabled agent - has access to company documents\nconst ragResponse = await forge.runAgent(\n  \"Knowledge Assistant\",\n  \"What are our professional development policies?\"\n);\n// Returns specific, accurate information from your documents\n\n// Regular agent - uses general knowledge only\nconst generalResponse = await forge.runAgent(\n  \"General Assistant\",\n  \"What are our professional development policies?\"\n);\n// Returns generic advice, not company-specific information\n```\n\n#### RAG Workflow Features\n\n- **Document Chunking**: Intelligent text splitting with configurable size and overlap\n- **Semantic Search**: Retrieves relevant documents using embedding similarity\n- **Error Handling**: Graceful fallback when ChromaDB is unavailable\n- **Team Integration**: RAG agents work seamlessly in team workflows\n- **Tool Integration**: RAG appears as a tool that agents can use when needed\n\n## Plugin System\n\nAgent Forge features a powerful plugin architecture with lifecycle hooks that enables you to extend framework functionality and implement cross-cutting concerns like logging, metrics, security, and caching.\n\n### Plugin Lifecycle Hooks\n\nPlugins can hook into various points in the framework's execution:\n\n- **Framework Lifecycle**: `FRAMEWORK_INITIALIZE`, `FRAMEWORK_READY`, `FRAMEWORK_SHUTDOWN`\n- **Agent Lifecycle**: `AGENT_REGISTER`, `AGENT_BEFORE_RUN`, `AGENT_AFTER_RUN`, `AGENT_ERROR`\n- **LLM Lifecycle**: `LLM_BEFORE_REQUEST`, `LLM_AFTER_REQUEST`, `LLM_STREAM_START`, `LLM_STREAM_END`\n- **Tool Lifecycle**: `TOOL_BEFORE_EXECUTE`, `TOOL_AFTER_EXECUTE`, `TOOL_ERROR`\n- **Team/Workflow Lifecycle**: `TEAM_BEFORE_RUN`, `TEAM_AFTER_RUN`, `WORKFLOW_BEFORE_RUN`, `WORKFLOW_AFTER_RUN`\n- **Logging Lifecycle**: `LOG_ENTRY_CREATED`, `LOG_ERROR_OCCURRED`, `LOG_CRITICAL_OCCURRED`\n\n### Creating Custom Plugins\n\nTo create a custom plugin, extend the `Plugin` class:\n\n```ts\nimport { Plugin, PluginLifecycleHooks, type PluginHookData } from \"agent-forge\";\n\nexport class SecurityPlugin extends Plugin {\n  readonly name = \"security\";\n  readonly version = \"1.0.0\";\n  readonly priority = 90; // Higher numbers run first\n\n  getHooks() {\n    return {\n      [PluginLifecycleHooks.AGENT_BEFORE_RUN]: this.validateInput.bind(this),\n      [PluginLifecycleHooks.TOOL_BEFORE_EXECUTE]:\n        this.validateToolCall.bind(this),\n    };\n  }\n\n  private validateInput(data: PluginHookData): any {\n    const { input } = data.payload;\n\n    // Your validation logic here\n    if (this.containsSensitiveData(input)) {\n      this.log(\"⚠️ Input contains sensitive data - sanitizing\", \"warn\");\n      return { ...data.payload, input: this.sanitizeInput(input) };\n    }\n\n    return data.payload;\n  }\n\n  private validateToolCall(data: PluginHookData): any {\n    const { toolName } = data.payload;\n\n    if (!this.isToolAllowed(toolName)) {\n      throw new Error(`Tool ${toolName} is not allowed by security policy`);\n    }\n\n    return data.payload;\n  }\n\n  // ... implementation details\n}\n```\n\n### Using Plugins\n\n#### With Decorators\n\n```ts\nimport { plugin, forge, llmProvider, agent } from \"agent-forge\";\n\n@plugin(new SecurityPlugin()) // Your custom plugin\n@plugin(new LoggingPlugin()) // Your custom logging plugin\n@llmProvider(\"openai\", { apiKey: process.env.LLM_API_KEY })\n@forge()\nclass MyApplication {\n  static forge: AgentForge;\n\n  static async run() {\n    // Initialize framework with plugins\n    await MyApplication.forge.initialize();\n\n    // Register agent classes with readyForge\n    const agentClasses = [YourAgentClass]; // Replace with your actual agent classes\n    await readyForge(MyApplication, agentClasses);\n\n    // ... your application logic\n\n    // Shutdown cleanly\n    await MyApplication.forge.shutdown();\n  }\n}\n```\n\n#### Programmatically\n\n```ts\nimport { AgentForge } from \"agent-forge\";\n\nconst forge = new AgentForge();\n\n// Register plugins\nawait forge.registerPlugin(new CustomLoggingPlugin());\nawait forge.registerPlugin(new CustomMetricsPlugin());\n\n// Initialize framework\nawait forge.initialize();\n\n// Plugin manager access\nconst pluginManager = forge.getPluginManager();\nconst enabledPlugins = pluginManager.getEnabledPlugins();\nconst loggingPlugin = pluginManager.getPlugin(\"logging\");\n```\n\n### Plugin Management\n\n```ts\n// Get plugin manager\nconst pluginManager = forge.getPluginManager();\n\n// List all plugins\nconst allPlugins = pluginManager.getAllPlugins();\nconst enabledPlugins = pluginManager.getEnabledPlugins();\n\n// Get specific plugin\nconst customPlugin = pluginManager.getPlugin(\"custom\") as CustomPlugin;\n\n// Enable/disable plugins\nconst loggingPlugin = pluginManager.getPlugin(\"logging\");\nloggingPlugin?.disable();\nloggingPlugin?.enable();\n\n// Unregister plugin\nawait pluginManager.unregisterPlugin(\"security\");\n```\n\n### Plugin Use Cases\n\nThe plugin architecture enables many powerful use cases:\n\n- **Development**: Debugging, performance profiling, step-through execution\n- **Production**: Monitoring, alerting, health checks, SLA tracking\n- **Security**: Input validation, output sanitization, access control\n- **Performance**: Caching, connection pooling, request batching\n- **Integration**: Database logging, webhook notifications, external APIs\n- **Compliance**: Audit trails, data retention, privacy controls\n\n### Plugin Example\n\nCreate custom plugins to extend Agent Forge functionality (see the complete plugin example at `src/examples/plugin-example/):\n\n- Security validation and input sanitization\n- Caching and performance optimization\n- Custom logging and metrics collection\n- Plugin management and lifecycle hooks\n- Integration with teams and workflows\n\n## Decorators Reference\n\n- `@agent(config)`: Attach agent config to a class.\n- `@tool(ToolClass)`: Add a tool to an agent. Can be used multiple times to add multiple tools.\n- `@llmProvider(provider, config)`: Set LLM provider for a class.\n- `@forge(config?)`: Attach a static AgentForge instance to a class with optional configuration including logging levels.\n- `@plugin(pluginInstance)`: Register a plugin with the framework.\n- `@a2aServer(options)`: Expose an agent as an A2A server.\n- `@a2aClient(options)`: Connect an agent to a remote A2A server.\n- `@MCP(protocol, config)`: Attach MCP tools to an agent.\n- `@RateLimiter(config)`: Add rate limiting to an agent's tool usage.\n- `@RAGChromaDb(config)`: Add RAG (Retrieval-Augmented Generation) capabilities with ChromaDB to an agent.\n- `@Visualizer()`: Enable timeline visualization for team runs. When used above `@forge` and `@llmProvider`, it will automatically generate an interactive HTML timeline of all agent, manager, and task events after each run.\n\n**Usage Example:**\n\n```ts\nimport { Visualizer, forge, llmProvider, agent, tool } from \"agent-forge\";\nimport { AgentForge, Agent, WebSearchTool } from \"agent-forge\";\n\n@tool(WebSearchTool)\n@agent({\n  name: \"ManagerAgent\",\n  role: \"Manager\",\n  description: \"Delegates tasks to team members.\",\n  objective: \"Coordinate the team to solve complex tasks.\",\n  model: process.env.LLM_API_MODEL!,\n})\nclass ManagerAgent extends Agent {}\n\n@llmProvider(\"openai\", { apiKey: process.env.LLM_API_KEY })\n@Visualizer()\n@forge()\nclass TeamWithTimeline {\n  static forge: AgentForge;\n  // ...\n}\n```\n\nAfter running a team, an HTML timeline file will be written to the current directory (e.g., `team-run-timeline.html`).\n\n## Documentation\n\n- See the [docs/](docs/) directory for full documentation, API reference, and advanced usage.\n- Example projects: `src/examples/`\n\n## Contributing\n\nContributions are welcome! Please see [CONTRIBUTING.md](./CONTRIBUTING.md) for details.\n\n## License\n\nMIT\n\n**Agent Forge**: Build, orchestrate, and scale AI agents and teams.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffrostlogic-ab%2Fagent-forge","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffrostlogic-ab%2Fagent-forge","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffrostlogic-ab%2Fagent-forge/lists"}