Skip to content
Agentmart
Submit a tool

AGENTS.md · ag2ai/ag2

AGENTS.md from ag2ai/ag2: 242 lines covering AI-assisted contribution policy, Architecture Decision Records (ADR), Code Style Guidelines, Package Structure…

Template by ag2ai

IndexedApache-2.0★ 5,016
Write a review

Install

Works with Codex, Cursor, GitHub Copilot, Gemini CLI, OpenCode, Claude Code. Read the repository before you give any tool access to your data.

curl -fsSL https://raw.githubusercontent.com/ag2ai/ag2/main/AGENTS.md -o AGENTS.md

Read it and adapt it to your project before use.

Get the weekly diff

The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.

We use your email only for this newsletter. Privacy

About

The AGENTS.md file that ag2ai/ag2 (5,015 stars) keeps for coding agents. It has 242 lines in 7 sections: AI-assisted contribution policy; Architecture Decision Records (ADR); Code Style Guidelines; Package Structure; Builtin Tools; Subagent Delegation; LLM Provider Clients. Use it as a model for your own project's instructions.

Use cases: prompt-engineering

No reviews yet. Installed it? Reviews come from verified installers only. How reviews work

What's in it

An AGENTS.md file: instructions coding agents (Codex, Cursor, Copilot, Gemini CLI and others) read before working in a repo.

For
Codex, Cursor, GitHub Copilot, Gemini CLI, OpenCode, Claude Code
Length
242 lines
File
AGENTS.md

Sections

  1. AI-assisted contribution policy
  2. Architecture Decision Records (ADR)
  3. Code Style Guidelines
  4. Package Structure
  5. Builtin Tools
  6. Subagent Delegation
  7. LLM Provider Clients

First lines (shown under the repo's Apache-2.0 license)

# AG2 Development Guidelines

## AI-assisted contribution policy

Before opening a PR, read and follow `.github/AI_POLICY.md`.

- Do not open PRs with unverified AI-generated code or text.
- Ensure the PR description explains the real problem or use case and accurately reflects the diff.
- Include validation and testing information in the PR body.
- Be prepared to explain and revise the contribution in response to reviewer questions.
- Write the PR description using `.github/PULL_REQUEST_TEMPLATE.md`. Keep its section headings (`## Why are these changes needed?`, `## Related issue number`, `## Checks`, `## AI assistance`), fill each one in, and only check a checklist box once it is actually true.

## Architecture Decision Records (ADR)

Cross-cutting and hard-to-reverse design decisions are recorded in `docs/adr/`, sequentially numbered (`0001-*.md`, `0002-*.md`, …) with `status` / `date` frontmatter and a short Context / Decision / Consequences body.

- **Consult them before changing established public API or architecture.** They explain *why* something is the way it is — e.g. `0003-eval-run-api-takes-agent-instances.md` records that the eval `run_*` API takes prebuilt `Agent` instances (not factories) and explicitly-built `Suite`s. If a change contradicts an ADR, supersede it rather than silently reverting the code.
- **Add one when a decision qualifies**: it is hard to reverse, surprising without context (a reader would assume the opposite), and the result of a real trade-off. Scan `docs/adr/` for the highest number and increment. Keep it short — recording *that* a decision was made and *why* is the value.

## Code Style Guidelines

- Do not use `from __future__ import annotations`.
- With `@contextmanager` / `@asynccontextmanager`, annotate the return type as `Generator[T]` / `AsyncGenerator[T]`, never `Iterator[T]` / `AsyncIterator[T]`. The decorator needs a real generator — it calls `throw()` / `athrow()` on it — so the iterator form is an under-specification that typeshed marks deprecated. Import them from `collections.abc` (not `typing`) and omit the default send type: `AsyncGenerator[None]`, not `AsyncGenerator[None, None]`.
- Do not use global variables or top-level side-effect function calls unless the user explicitly allows it.
- For filesystem paths, use `pathlib.Path` internally. Public signatures should accept `str | os.PathLike[str]`.
- Top-level imports from `ag2.*` are for common APIs that are broadly reusable across scenarios and core agent flows.
  Good: `ag2.[Input]` — common structures usable in `await agent.ask(Input())` and as tool results.
  Bad: `ag2.middleware.BaseMiddleware` — this is advanced/specialized and should be imported only when implementing custom middleware.
- Do not use function-level imports unless the user explicitly allows it.
  ```python
  # === BAD - import inside function ===
  def execute_tool():
      from .tool import Tool

      ...


  # === GOOD - top-level import ===
  from .tool import Tool


  def execute_tool(): ...
  ```
- Do not create nested functions inside runtime execution paths.
  ```python
  # === BAD - function will be created each call ===
  def execute_tool():
      def _inner_function():
          pass

      _inner_function()


  # === GOOD - function created once, executed each call ===
  def execute_tool():
      _inner_function()


  def _inner_function():
      pass


  # === GOOD - decorator executed import time, so we can use closure functions here ===
  def decorator(func):
      def wrapper():
          return func()

      return wrapper
  ```
- Do not perform side effects in initialization methods. Apply side effects only at runtime.
  ```python
  # === BAD - create directory in initial method ===
  class KnowledgeStore:
      def __init__(self, path: str | os.PathLike[str]) -> None:
          self.path = Path(path)
          # side effect - directory creation
          self.path.parent.mkdir(parents=True, exist_ok=True)

      def run(self) -> None: ...


  # === GOOD - create directory in runtime method ===
  class KnowledgeStore:
      def __init__(self, path: str | os.PathLike[str]) -> None:
          self.path = Path(path)

      def run(self) -> None:
          self.path.parent.mkdir(parents=True, exist_ok=True)
          ...
  ```

## Package Structure

`ag2/` is a protocol-driven async agent framework. Key modules:

| Module | Purpose | Key Exports |
|--------|---------|-------------|
| `agent.py` | Core agent loop and reply handling | `Agent`, `AgentReply` |
| `annotations.py` | Type annotations for dependency injection | `Context`, `Inject`, `Variable` |
| `context.py` | Runtime context (stream, dependencies, variables, prompt) | `Context` dataclass, `Stream` protocol |
| `stream.py` | In-memory event pub/sub | `MemoryStream`, `SubStream` |
| `events/` | Event types for the agent loop | `BaseEvent`, `ModelRequest`, `ModelResponse`, `ToolCallEvent`, `ToolResultEvent`, `Usage`, … |
| `config/` | LLM provider clients (see [below](#llm-provider-clients)) | `ModelConfig`, `LLMClient`, `AnthropicConfig`, `OpenAIConfig`, `GeminiConfig`, … |
| `tools/` | Ready-to-use tools | `tool`, `Toolkit`, `ToolResult`, `CodeExecutionTool`, `ShellTool`, `WebSearchTool`, … |
| `tools/types.py` | Tool abstractions & schema types | `Tool`, `FunctionTool`, `ClientTool`, `Toolkit`, `ToolSchema`, … |
| `tools/subagents/` | Agent-to-agent delegation | `subagent_tool`, `run_task`, `persistent_stream`, `StreamFactory` |
| `eval/` | Offline evaluation framework | `run`, `scorer`, `EvalTarget`, `Suite`, `Task`, `Trace`, `RunResult`, `Feedback`, `BudgetThresholds`, plus prebuilts under `eval.scorers` |
| `middleware/` | Request/response interception | `BaseMiddleware`, `Middleware`, `LoggingMiddleware`, `RetryMiddleware`, `TokenLimiter`, `HistoryLimiter`, `MiddlewareDescription`, … |
| `response/` | Structured output validation | `ResponseSchema`, `PromptedSchema`, `ResponseProto`, `response_schema` |
| `history.py` | Conversation history storage | `History`, `Storage`, `MemoryStorage` |
| `hitl.py` | Human-in-the-loop hooks | — |
| `streams/` | Persistent stream backends (e.g. Redis) | — |

### Public API (`ag2`)

Top-level modules:
- `ag2` - top-level module with most basic functionality
- `ag2.types` - Type aliases and constants
- `ag2.config` - LLM provider clients (see [below](#llm-provider-clients))
- `ag2.tools` - Tool system — builtin + user-defined (see [below](#builtin-tools))
- `ag2.tools.subagents` - Agent-to-agent delegation (see [below](#subagent-delegation))
- `ag2.testing` - Testing utilities
- `ag2.middleware` - Request/response interception (see [below](#middleware))
- `ag2.observers` - Reusable observer implementations
- `ag2.eval` - Offline evaluation framework (datasets, scorers, runner, persistence)

Advanced modules:
- `ag2.events` - Event types for the agent loop
- `ag2.streams` - Persistent stream backends (e.g. Redis)
- `ag2.watch` - Watch system for triggering observers
- `ag2.knowledge` - Knowledge management
- `ag2.plugin` - Plugin system

### Re-export rules

All implementations must be re-exported from their public module's `__init__.py` and listed in `__all__`. If an implementation requires third-party dependencies, wrap the import in a `try/except ImportError` block and register a missing-dependency fallback so users get a clear install hint instead of an unexplained `ImportError` (see `ag2/config/__init__.py`, `ag2/middleware/builtin/__init__.py` as the reference pattern). Two fallbacks exist:

- **Core modules** use **optional dependencies** shipped as pyproject extras — fall back via `missing_optional_dependency`, which hints `pip install "ag2[<extra>]"`.
- **Extensions** (`ag2/extensions/`) are **not** shipped as extras — declare their third-party packages as **additional dependencies** and fall back via `missing_additional_dependency`, which hints the upstream package directly (e.g. `pip install "daytona>=0.171.0,<1"`).

Either way, add the third-party package to the `optionals` **dependency group** in `pyproject.toml` (PEP 735 — CI-only, never part of `pip install ag2`) so the test workflow installs it. Tests guarded by `pytest.importorskip("<package>")` are silently skipped otherwise, and CI still passes.

### Design principles

- **Protocols over inheritance**: `LLMClient`, `ModelConfig`, `Stream`, `Storage` are all `Protocol` classes — implementations satisfy them structurally. `Tool` is the exception: it is an `ABC` that tool kinds subclass (see [ADR 0002](docs/adr/0002-tool-composite-hierarchy.md)).
- **Async throughout**: all major operations (`ask`, tool execution, LLM calls) are async. Sync tool functions run via `sync_to_thread`.
- **Event-driven**: all agent-loop communication flows through the `Stream` as typed events.
- **Dependency injection**: all user-provided functions (tools, prompt hooks, HITL, etc.) use `Context`, `Inject`, and `Variable` annotations; resolution is handled by `fast_depends`.

## Builtin Tools

Builtin tools live in `ag2/tools/builtin/`. Each tool has:
- A `ToolSchema` dataclass (provider-neutral capability flag)
- A `Tool` class (constructs the schema, resolves Variables)

### API Design

- Use `version` as the public parameter name on Tool constructors for provider-versioned tools (e.g., `WebSearchTool(version="web_search_20260209")`). The schema field may use a more specific name internally (e.g., `web_search_version`) — the Tool maps between them.
- Tool constructor parameters that accept runtime values must also accept `Variable` for deferred context resolution (e.g., `max_uses: int | Variable | None`).
- Tools with no configurable parameters (e.g., `MemoryTool`, `CodeExecutionTool`) should still accept a `version` keyword argument to allow version pinning.

Signals

Stars
5,016
Forks
758
Open issues
30
Last commit (this folder)
Oct 3, 2026 (26 days ago)
Last release
Oct 21, 2026 (8 days ago)

From GitHub (fetched Oct 24, 2026).

Details

License
Apache-2.0
First seen
Oct 24, 2026
Last checked
Oct 24, 2026
Cite this page

AGENTS.md · ag2ai/ag2. Agent Mart. https://agentmart.dev/templates/ag2ai-ag2-agents-md (last updated 2026-10-24)