CLAUDE.md
classic/forge/CLAUDE.mdCLAUDE.md
Quality
73/100
Scores the file, not the repository.Length
1,391 words
38 headings · 25 code blocksRepository
186k
— · pushed 0 days agoLast changed
3 days ago
First indexed 3 days ago.1# CLAUDE.md23This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.45## Quick Reference67All commands run from the `classic/` directory (parent of this directory):89```bash10# Run forge agent server (port 8000)11poetry run python -m forge1213# Run forge tests14poetry run pytest forge/tests/15poetry run pytest forge/tests/ --cov=forge16poetry run pytest -k test_name17```1819## Entry Point2021`__main__.py` → loads `.env` → configures logging → starts Uvicorn with hot-reload on port 80002223The app is created in `app.py`:24```python25agent = ForgeAgent(database=database, workspace=workspace)26app = agent.get_agent_app()27```2829## Directory Structure3031```32forge/33├── __main__.py # Entry: uvicorn server startup34├── app.py # FastAPI app creation35├── agent/ # Core agent framework36│ ├── base.py # BaseAgent abstract class37│ ├── forge_agent.py # Reference implementation38│ ├── components.py # AgentComponent base classes39│ └── protocols.py # Protocol interfaces40├── agent_protocol/ # Agent Protocol standard41│ ├── agent.py # ProtocolAgent mixin42│ ├── api_router.py # FastAPI routes43│ └── database/ # Task/step persistence44├── command/ # Command system45│ ├── command.py # Command class46│ ├── decorator.py # @command decorator47│ └── parameter.py # CommandParameter48├── components/ # Built-in components49│ ├── action_history/ # Track & summarize actions50│ ├── code_executor/ # Python & shell execution51│ ├── context/ # File/folder context52│ ├── file_manager/ # File operations53│ ├── git_operations/ # Git commands54│ ├── image_gen/ # DALL-E & SD55│ ├── system/ # Core directives + finish56│ ├── user_interaction/ # User prompts57│ ├── watchdog/ # Loop detection58│ └── web/ # Search & Selenium59├── config/ # Configuration models60├── llm/ # LLM integration61│ └── providers/ # OpenAI, Anthropic, Groq, etc.62├── file_storage/ # Storage abstraction63│ ├── base.py # FileStorage ABC64│ ├── local.py # LocalFileStorage65│ ├── s3.py # S3FileStorage66│ └── gcs.py # GCSFileStorage67├── models/ # Core data models68├── content_processing/ # Text/HTML utilities69├── logging/ # Structured logging70└── json/ # JSON parsing utilities71```7273## Core Abstractions7475### BaseAgent (`agent/base.py`)7677Abstract base for all agents. Generic over proposal type.7879```python80class BaseAgent(Generic[AnyProposal], metaclass=AgentMeta):81 def __init__(self, settings: BaseAgentSettings)82```8384**Must Override:**85```python86async def propose_action(self) -> AnyProposal87async def execute(self, proposal: AnyProposal, user_feedback: str) -> ActionResult88async def do_not_execute(self, denied_proposal: AnyProposal, user_feedback: str) -> ActionResult89```9091**Key Methods:**92```python93async def run_pipeline(protocol_method, *args, retry_limit=3) -> list94# Executes protocol across all matching components with retry logic9596def dump_component_configs(self) -> str # Serialize configs to JSON97def load_component_configs(self, json: str) # Restore configs98```99100**Configuration (`BaseAgentConfiguration`):**101```python102fast_llm: ModelName = "gpt-3.5-turbo-16k"103smart_llm: ModelName = "gpt-4"104big_brain: bool = True # Use smart_llm105cycle_budget: Optional[int] = 1 # Steps before approval needed106send_token_limit: Optional[int] # Prompt token budget107```108109### Component System (`agent/components.py`)110111**AgentComponent** - Base for all components:112```python113class AgentComponent(ABC):114 _run_after: list[type[AgentComponent]] = []115 _enabled: bool | Callable[[], bool] = True116 _disabled_reason: str = ""117118 def run_after(self, *components) -> Self # Set execution order119 def enabled(self) -> bool # Check if active120```121122**ConfigurableComponent** - Components with Pydantic config:123```python124class ConfigurableComponent(Generic[BM]):125 config_class: ClassVar[type[BM]] # Set in subclass126127 @property128 def config(self) -> BM # Get/create config from env129```130131**Component Discovery:**1321. Agent assigns components: `self.foo = FooComponent()`1332. `AgentMeta.__call__` triggers `_collect_components()`1343. Components are topologically sorted by `run_after` dependencies1354. Disabled components skipped during pipeline execution136137### Protocols (`agent/protocols.py`)138139Protocols define what components CAN do:140141```python142class DirectiveProvider(AgentComponent):143 def get_constraints(self) -> Iterator[str]144 def get_resources(self) -> Iterator[str]145 def get_best_practices(self) -> Iterator[str]146147class CommandProvider(AgentComponent):148 def get_commands(self) -> Iterator[Command]149150class MessageProvider(AgentComponent):151 def get_messages(self) -> Iterator[ChatMessage]152153class AfterParse(AgentComponent, Generic[AnyProposal]):154 def after_parse(self, result: AnyProposal) -> None155156class AfterExecute(AgentComponent):157 def after_execute(self, result: ActionResult) -> None158159class ExecutionFailure(AgentComponent):160 def execution_failure(self, error: Exception) -> None161```162163**Pipeline execution:**164```python165results = await self.run_pipeline(CommandProvider.get_commands)166# Iterates all components implementing CommandProvider167# Collects all yielded Commands168# Handles retries on ComponentEndpointError169```170171## LLM Providers (`llm/providers/`)172173### MultiProvider174175Routes to correct provider based on model name:176177```python178class MultiProvider:179 async def create_chat_completion(180 self,181 model_prompt: list[ChatMessage],182 model_name: ModelName,183 **kwargs184 ) -> ChatModelResponse185186 async def get_available_chat_models(self) -> Sequence[ChatModelInfo]187```188189### Supported Models190191```python192# OpenAI193OpenAIModelName.GPT3, GPT3_16k, GPT4, GPT4_32k, GPT4_TURBO, GPT4_O194195# Anthropic196AnthropicModelName.CLAUDE3_OPUS, CLAUDE3_SONNET, CLAUDE3_HAIKU197AnthropicModelName.CLAUDE3_5_SONNET, CLAUDE3_5_SONNET_v2, CLAUDE3_5_HAIKU198AnthropicModelName.CLAUDE4_SONNET, CLAUDE4_OPUS, CLAUDE4_5_OPUS199200# Groq201GroqModelName.LLAMA3_8B, LLAMA3_70B, MIXTRAL_8X7B202```203204### Key Types205206```python207class ChatMessage(BaseModel):208 role: Role # USER, SYSTEM, ASSISTANT, TOOL, FUNCTION209 content: str210211class AssistantFunctionCall(BaseModel):212 name: str213 arguments: dict[str, Any]214215class ChatModelResponse(BaseModel):216 completion_text: str217 function_calls: list[AssistantFunctionCall]218```219220## File Storage (`file_storage/`)221222Abstract interface for file operations:223224```python225class FileStorage(ABC):226 def open_file(self, path, mode="r", binary=False) -> IO227 def read_file(self, path, binary=False) -> str | bytes228 async def write_file(self, path, content) -> None229 def list_files(self, path=".") -> list[Path]230 def list_folders(self, path=".", recursive=False) -> list[Path]231 def delete_file(self, path) -> None232 def exists(self, path) -> bool233 def clone_with_subroot(self, subroot) -> FileStorage234```235236**Implementations:** `LocalFileStorage`, `S3FileStorage`, `GCSFileStorage`237238## Command System (`command/`)239240### @command Decorator241242```python243@command(244 names=["greet", "hello"],245 description="Greet a user",246 parameters={247 "name": JSONSchema(type=JSONSchema.Type.STRING, required=True),248 "greeting": JSONSchema(type=JSONSchema.Type.STRING, required=False),249 },250)251def greet(self, name: str, greeting: str = "Hello") -> str:252 return f"{greeting}, {name}!"253```254255### Providing Commands256257```python258class MyComponent(CommandProvider):259 def get_commands(self) -> Iterator[Command]:260 yield self.greet # Decorated method becomes Command261```262263## Built-in Components264265| Component | Protocols | Purpose |266|-----------|-----------|---------|267| `SystemComponent` | DirectiveProvider, MessageProvider, CommandProvider | Core directives, `finish` command |268| `FileManagerComponent` | DirectiveProvider, CommandProvider | read/write/list files |269| `CodeExecutorComponent` | CommandProvider | Python & shell execution (Docker) |270| `WebSearchComponent` | DirectiveProvider, CommandProvider | DuckDuckGo & Google search |271| `WebPlaywrightComponent` | DirectiveProvider, CommandProvider | Browser automation (Playwright) |272| `ActionHistoryComponent` | MessageProvider, AfterParse, AfterExecute | Track & summarize history |273| `WatchdogComponent` | AfterParse | Loop detection, LLM switching |274| `ContextComponent` | MessageProvider, CommandProvider | Keep files in prompt context |275| `ImageGeneratorComponent` | CommandProvider | DALL-E, Stable Diffusion |276| `GitOperationsComponent` | CommandProvider | Git commands |277| `UserInteractionComponent` | CommandProvider | `ask_user` command |278279## Configuration280281### BaseAgentSettings282283```python284class BaseAgentSettings(SystemSettings):285 agent_id: str286 ai_profile: AIProfile # name, role, goals287 directives: AIDirectives # constraints, resources, best_practices288 task: str289 config: BaseAgentConfiguration290```291292### UserConfigurable Fields293294```python295class MyConfig(SystemConfiguration):296 api_key: SecretStr = UserConfigurable(from_env="API_KEY", exclude=True)297 max_retries: int = UserConfigurable(default=3, from_env="MAX_RETRIES")298299config = MyConfig.from_env() # Load from environment300```301302## Agent Protocol (`agent_protocol/`)303304REST API for task-based interaction:305306```307POST /ap/v1/agent/tasks # Create task308GET /ap/v1/agent/tasks # List tasks309GET /ap/v1/agent/tasks/{id} # Get task310POST /ap/v1/agent/tasks/{id}/steps # Execute step311GET /ap/v1/agent/tasks/{id}/steps # List steps312GET /ap/v1/agent/tasks/{id}/artifacts # List artifacts313```314315**ProtocolAgent mixin** provides these endpoints + database persistence.316317## Testing318319**Fixtures** (`conftest.py`):320- `storage` - Temporary LocalFileStorage321322Run from the `classic/` directory:323```bash324poetry run pytest forge/tests/ # All forge tests325poetry run pytest forge/tests/ --cov=forge # With coverage326```327328**Note**: Tests requiring API keys (OPENAI_API_KEY, ANTHROPIC_API_KEY) will be skipped if not set.329330## Creating a Custom Component331332```python333from forge.agent.components import AgentComponent, ConfigurableComponent334from forge.agent.protocols import CommandProvider335from forge.command import command336from forge.models.json_schema import JSONSchema337338class MyConfig(BaseModel):339 setting: str = "default"340341class MyComponent(CommandProvider, ConfigurableComponent[MyConfig]):342 config_class = MyConfig343344 def get_commands(self) -> Iterator[Command]:345 yield self.my_command346347 @command(348 names=["mycmd"],349 description="Do something",350 parameters={"arg": JSONSchema(type=JSONSchema.Type.STRING, required=True)},351 )352 def my_command(self, arg: str) -> str:353 return f"Result: {arg}"354```355356## Creating a Custom Agent357358```python359from forge.agent.forge_agent import ForgeAgent360361class MyAgent(ForgeAgent):362 def __init__(self, database, workspace):363 super().__init__(database, workspace)364 self.my_component = MyComponent()365366 async def propose_action(self) -> ActionProposal:367 # 1. Collect directives368 constraints = await self.run_pipeline(DirectiveProvider.get_constraints)369 resources = await self.run_pipeline(DirectiveProvider.get_resources)370371 # 2. Collect commands372 commands = await self.run_pipeline(CommandProvider.get_commands)373374 # 3. Collect messages375 messages = await self.run_pipeline(MessageProvider.get_messages)376377 # 4. Build prompt and call LLM378 response = await self.llm_provider.create_chat_completion(379 model_prompt=messages,380 model_name=self.config.smart_llm,381 functions=function_specs_from_commands(commands),382 )383384 # 5. Parse and return proposal385 return ActionProposal(386 thoughts=response.completion_text,387 use_tool=response.function_calls[0],388 raw_message=AssistantChatMessage(content=response.completion_text),389 )390```391392## Key Patterns393394### Component Ordering395```python396self.component_a = ComponentA()397self.component_b = ComponentB().run_after(self.component_a)398```399400### Conditional Enabling401```python402self.search = WebSearchComponent()403self.search._enabled = bool(os.getenv("GOOGLE_API_KEY"))404self.search._disabled_reason = "No Google API key"405```406407### Pipeline Retry Logic408- `ComponentEndpointError` → retry same component (3x)409- `EndpointPipelineError` → restart all components (3x)410- `ComponentSystemError` → restart all pipelines411412## Key Files Reference413414| Purpose | Location |415|---------|----------|416| Entry point | `__main__.py` |417| FastAPI app | `app.py` |418| Base agent | `agent/base.py` |419| Reference agent | `agent/forge_agent.py` |420| Components base | `agent/components.py` |421| Protocols | `agent/protocols.py` |422| LLM providers | `llm/providers/` |423| File storage | `file_storage/` |424| Commands | `command/` |425| Built-in components | `components/` |426| Agent Protocol | `agent_protocol/` |427
Also in Significant-Gravitas/AutoGPT
Diff this repo’s formatsOne repository carrying more than one format is the comparison this product exists for: does anyone actually write different content in each file, or is one a copy of the other?
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| Significant-Gravitas/AutoGPTautogpt_platform/frontend/src/tests/AGENTS.md · 186k | AGENTS.md | teststylearchtypes+2 | 81/100 | 3 days ago | |
| Significant-Gravitas/AutoGPT.github/copilot-instructions.md · 186k | Copilot instructions | setupbuildtestlint-format+10 | 88/100 | 3 days ago | |
| Significant-Gravitas/AutoGPTAGENTS.md · 186k | AGENTS.md | teststylearchgit+1 | 87/100 | 3 days ago | |
| Significant-Gravitas/AutoGPTautogpt_platform/AGENTS.md · 186k | AGENTS.md | setuptestarchtesting-strategy+3 | 77/100 | 3 days ago | |
| Significant-Gravitas/AutoGPTautogpt_platform/backend/AGENTS.md · 186k | AGENTS.md | setuptestlint-formatstyle+9 | 81/100 | 3 days ago | |
| Significant-Gravitas/AutoGPTautogpt_platform/backend/backend/copilot/graphiti/AGENTS.md · 186k | AGENTS.md | styleperformance | 66/100 | 3 days ago | |
| Significant-Gravitas/AutoGPTautogpt_platform/frontend/AGENTS.md · 186k | AGENTS.md | setupbuildtestlint-format+7 | 96/100 | 3 days ago | |
| Significant-Gravitas/AutoGPTclassic/CLAUDE.md · 186k | CLAUDE.md | setuptestlint-formatstyle+7 | 89/100 | 3 days ago | |
| Significant-Gravitas/AutoGPTclassic/direct_benchmark/CLAUDE.md · 186k | CLAUDE.md | setuptestlint-formatarch+4 | 78/100 | 3 days ago | |
| Significant-Gravitas/AutoGPTclassic/original_autogpt/CLAUDE.md · 186k | CLAUDE.md | testarchuiperformance+2 | 90/100 | 3 days ago | |
| Significant-Gravitas/AutoGPT.claude/skills/vercel-react-best-practices/AGENTS.md · 186k | AGENTS.md | buildlint-formatstyledependencies+4 | 61/100 | 3 days ago |
Diff against autogpt_platform/frontend/src/tests/AGENTS.md Diff against .github/copilot-instructions.md Diff against AGENTS.md Diff against autogpt_platform/AGENTS.md Diff against autogpt_platform/backend/AGENTS.md Diff against autogpt_platform/backend/backend/copilot/graphiti/AGENTS.md Diff against autogpt_platform/frontend/AGENTS.md Diff against classic/CLAUDE.md Diff against classic/direct_benchmark/CLAUDE.md Diff against classic/original_autogpt/CLAUDE.md Diff against .claude/skills/vercel-react-best-practices/AGENTS.md
Similar configs
Same format, overlapping stack, ranked by quality.
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| Adit-Jain-srm/NightmareNetCLAUDE.md · 45 | CLAUDE.md | buildtestlint-formatstyle+6 | 100/100 | 3 days ago | |
| nimbalyst/nimbalystpackages/android/CLAUDE.md · 1.4k | CLAUDE.md | setupbuildstylearch+2 | 100/100 | 3 days ago | |
| dotCMS/corecore-web/CLAUDE.md · 949 | CLAUDE.md | teststylearchtesting-strategy+3 | 100/100 | 3 days ago | |
| microsoft/playwrightCLAUDE.md · 94k | CLAUDE.md | buildtestlint-formatstyle+7 | 100/100 | 3 days ago | |
| filamentphp/filamentCLAUDE.md · 32k | CLAUDE.md | buildtestlint-formatstyle+7 | 100/100 | 3 days ago | |
| bagisto/bagistoCLAUDE.md · 28k | CLAUDE.md | setupbuildteststyle+5 | 100/100 | 3 days ago | |
| dotCMS/coreCLAUDE.md · 949 | CLAUDE.md | setupbuildteststyle+7 | 99/100 | today | |
| carrot-foundation/middle-earthCLAUDE.md · 0 | CLAUDE.md | setupbuildtestlint-format+6 | 97/100 | 3 days ago |
