Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
214 changes: 214 additions & 0 deletions sdk/agentserver/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
# AGENTS.md

This file provides comprehensive guidance to Coding Agents(Codex, Claude Code, GitHub Copilot, etc.) when working with Python code in this repository.


## 🎯 (Read-first) Project Awareness & Context

- **Always read `PLANNING.md`** at the start of a new conversation to understand the project's architecture, goals, style, and constraints.
- **Check `TASK.md`** before starting a new task. If the task isn't listed, add it with a brief description and today's date.

## 🏆 Core Development Philosophy

### KISS (Keep It Simple, Stupid)

Simplicity should be a key goal in design. Choose straightforward solutions over complex ones whenever possible. Simple solutions are easier to understand, maintain, and debug.

### YAGNI (You Aren't Gonna Need It)

Avoid building functionality on speculation. Implement features only when they are needed, not when you anticipate they might be useful in the future.

### Design Principles

- **Dependency Inversion**: High-level modules should not depend on low-level modules. Both should depend on abstractions.
- **Open/Closed Principle**: Software entities should be open for extension but closed for modification.
- **Single Responsibility**: Each function, class, and module should have one clear purpose.
- **Fail Fast**: Check for potential errors early and raise exceptions immediately when issues occur.
- **Encapsulation**: Hide internal state and require all interaction to be performed through an object's methods.

### Implementation Patterns

- **Type-Safe**: Prefer explicit, type‑safe structures (TypedDicts, dataclasses, enums, unions) over Dict, Any, or other untyped containers, unless there is no viable alternative.
- **Explicit validation at boundaries**: Validate inputs and identifiers early; reject malformed descriptors and missing required fields.
- **Separation of resolution and execution**: Keep discovery/selection separate from invocation to allow late binding and interchangeable implementations.
- **Context-aware execution**: Thread request/user context through calls via scoped providers; avoid global mutable state.
- **Cache with safety**: Use bounded TTL caching with concurrency-safe in-flight de-duplication; invalidate on errors.
- **Stable naming and deterministic mapping**: Derive stable, unique names deterministically to avoid collisions.
- **Graceful defaults, loud misconfiguration**: Provide sensible defaults when optional data is missing; raise clear errors when required configuration is absent.
- **Thin integration layers**: Use adapters/middleware to translate between layers without leaking internals.

## ✅ Work Process (required)

- **Before coding**: confirm the task in `TASK.md` → **Now**.
- **While working**: Add new sub-tasks or TODOs discovered during development to `TASK.md` under a "Discovered During Work" section.
- **After finishing**: mark the task done immediately, and note what changed (files/areas) in `TASK.md`.
- **Update CHANGELOG.md only when required** by release policy.

### TASK.md template
```markdown
## Now (active)
- [ ] YYYY-MM-DD — <short task title>
- Scope: <what you will touch / not touch>
- Exit criteria: <tests passing / sample runs / files updated>

## Next (queued)
- [ ] YYYY-MM-DD — <task>

## Discovered During Work
- [ ] YYYY-MM-DD — <follow-up discovered while implementing something else>

## Done
- [x] YYYY-MM-DD — <task completed>
```

## 📎 Style & Conventions & Standards

### File and Function Limits

- **Never create a file longer than 500 lines of code**. If approaching this limit, refactor by splitting into modules.
- **Functions should be under 50 lines** with a single, clear responsibility.
- **Classes should be under 100 lines** and represent a single concept or entity.
- **Organize code into clearly separated modules**, grouped by feature or responsibility.
- **Line length should be max 120 characters**, as enforced by Ruff in `pyproject.toml`.
- **Use the standard repo workflow**: from the package root, run tests and linters via `tox` (for example, `tox -e pytest` or `tox -e pylint`) rather than relying on a custom virtual environment name.
- **Keep modules focused and cohesive**; split by feature responsibility when a file grows large or mixes concerns.
- **Avoid drive-by refactors** unless required by the task.
- **Preserve public API stability** and match existing patterns in the package you touch.

### Naming Conventions

- **Variables and functions**: `snake_case`
- **Classes**: `PascalCase`
- **Constants**: `UPPER_SNAKE_CASE`
- **Private attributes/methods**: `_leading_underscore`
- **Type aliases**: `PascalCase`
- **Enum values**: `UPPER_SNAKE_CASE`

### Project File Conventions

- **Follow per-package `pyproject.toml`** and `[tool.azure-sdk-build]` settings.
- **Do not edit generated code**.
- **Do not edit files with the header** `Code generated by Microsoft (R) Python Code Generator.`
- `sdk/agentserver/azure-ai-agentserver-core/azure/ai/agentserver/core/models/projects/`
- `sdk/agentserver/azure-ai-agentserver-core/azure/ai/agentserver/core/_version.py`
- `sdk/agentserver/azure-ai-agentserver-agentframework/azure/ai/agentserver/agentframework/_version.py`
- `sdk/agentserver/azure-ai-agentserver-langgraph/azure/ai/agentserver/langgraph/_version.py`
- **Do not introduce secrets or credentials.**
- **Do not disable TLS/SSL verification** without explicit approval.
- **Keep logs free of sensitive data.**

### Python Code Standards

- **Follow existing package patterns** and Azure SDK for Python guidelines.
- **Type hints and async patterns** should match existing code.
- **Respect Ruff settings** (line length 120, isort rules) in each package `pyproject.toml`.
- **Avoid new dependencies** unless necessary and approved.

### Docstring Standards
Use reStructuredText (reST) / Sphinx Style docstrings for all public functions, classes, and modules:

```python
def calculate_discount(
price: Decimal,
discount_percent: float,
min_amount: Decimal = Decimal("0.01")
) -> Decimal:
"""Calculate the discounted price for a product.

:param price: The original price of the product.
:type price: Decimal
:param discount_percent: The discount percentage to apply (0-100).
:type discount_percent: float
:param min_amount: The minimum amount after discount (default is 0.01).
:type min_amount: Decimal
:return: The price after applying the discount, not less than min_amount.
:rtype: Decimal
:raises ValueError: If discount_percent is not between 0 and 100.

Example:
Calculate a 15% discount on a $100 product:

.. code-block:: python

calculate_discount(Decimal("100.00"), 15.0)
"""
```

### Error Handling Standards

- Prefer explicit validation at API boundaries and raise errors **as early as possible**.
- Use standard Python exceptions (`ValueError`, `TypeError`, `KeyError`, etc.) when they accurately describe the problem.
- When a domain-specific error is needed, define a clear, documented exception type and reuse it consistently.
- Do **not** silently swallow exceptions. Either handle them meaningfully (with clear recovery behavior) or let them propagate.
- Preserve the original traceback when re-raising (`raise` without arguments) so issues remain diagnosable.
- Fail fast on programmer errors (e.g., inconsistent state, impossible branches) using assertions or explicit exceptions.
- For public APIs, validate user input and return helpful, actionable messages without leaking secrets or internal implementation details.

#### Exception Best Practices

- Avoid `except Exception:` and **never** use bare `except:`; always catch the most specific exception type possible.
- Keep `try` blocks **small** and focused so that it is clear which statements may raise the handled exception.
- When adding context to an error, use either `raise NewError("message") from exc` or log the context and re-raise with `raise`.
- Do not use exceptions for normal control flow; reserve them for truly exceptional or error conditions.
- When a function can raise non-obvious exceptions, document them in the docstring under a `:raises:` section.
- In asynchronous code, make sure exceptions are not lost in background tasks; gather and handle them explicitly where needed.

### Logging Standards

- Use the standard library `logging` module for all diagnostic output; **do not** use `print` in library or service code.
- Create a module-level logger via `logger = logging.getLogger(__name__)` and use it consistently within that module.
- Choose log levels appropriately:
- `logger.debug(...)` for detailed diagnostics and tracing.
- `logger.info(...)` for high-level lifecycle events (startup, shutdown, major state changes).
- `logger.warning(...)` for recoverable issues or unexpected-but-tolerated conditions.
- `logger.error(...)` for failures where the current operation cannot succeed.
- `logger.critical(...)` for unrecoverable conditions affecting process health.
- Never log secrets, credentials, access tokens, full connection strings, or sensitive customer data.
- When logging exceptions, prefer `logger.exception("message")` inside an `except` block so the traceback is included.
- Keep log messages clear and structured (include identifiers like request IDs, resource names, or correlation IDs when available).
## ⚠️ Important Notes

- **NEVER ASSUME OR GUESS** - When in doubt, ask for clarification
- **Always verify file paths and module names** before use
- **Keep this file (`AGENTS.md`) updated** when adding new patterns or dependencies
- **Test your code** - No feature is complete without tests
- **Document your decisions** - Future developers (including yourself) will thank you

## 📚 Documentation & Explainability

- **Keep samples runnable** and focused on SDK usage.
- **Follow third-party dependency guidance** in `CONTRIBUTING.md`.

## 🛠️ Development Environment

- **Use the repo-root virtual environment for validation work**: activate and use `azuresdk-env` from the repository root (`azure-sdk-for-python/azuresdk-env`) when running tests, linters, type checks, samples, or other validation commands.

### Dev Environment Setup

1. From the repository root, check for `azure-sdk-for-python/azuresdk-env`.
2. If it exists, activate it. If it does not exist, create it with `python -m venv azuresdk-env` and then activate it.
3. Install shared tooling into that environment: `uv` and `tox`.
4. Install the local AgentServer packages from source:
- `sdk/agentserver/azure-ai-agentserver-core/`
- `sdk/agentserver/azure-ai-agentserver-agentframework/`
- `sdk/agentserver/azure-ai-agentserver-langgraph/`
5. Install the common local test/runtime dependencies: `python-dotenv`, `pytest`, and `pytest-asyncio`.
6. Use that same environment for all subsequent local validation commands.

### ✅ Testing & Quality Gates (tox)

Run from a package root (e.g., `sdk/agentserver/azure-ai-agentserver-core`).

- `tox run -e sphinx -c ../../../eng/tox/tox.ini --root .`
- Docs output: `.tox/sphinx/tmp/dist/site/index.html`
- `tox run -e pylint -c ../../../eng/tox/tox.ini --root .`
- Uses repo `pylintrc`; `next-pylint` uses `eng/pylintrc`
- `tox run -e mypy -c ../../../eng/tox/tox.ini --root .`
- `tox run -e pyright -c ../../../eng/tox/tox.ini --root .`
- `tox run -e verifytypes -c ../../../eng/tox/tox.ini --root .`
- `tox run -e whl -c ../../../eng/tox/tox.ini --root .`
- `tox run -e sdist -c ../../../eng/tox/tox.ini --root .`
- `tox run -e samples -c ../../../eng/tox/tox.ini --root .` (runs all samples)
- `tox run -e apistub -c ../../../eng/tox/tox.ini --root .`

Check each package `pyproject.toml` under `[tool.azure-sdk-build]` to see which checks are enabled/disabled.
1 change: 1 addition & 0 deletions sdk/agentserver/CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@AGENTS.md
100 changes: 100 additions & 0 deletions sdk/agentserver/PLANNING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# 🧭 PLANNING.md

## 🎯 What this project is
AgentServer is a set of Python packages under `sdk/agentserver` that host agents for
Azure AI Foundry. The core package provides the runtime/server, tooling runtime, and
Responses API models, while the adapter packages wrap popular frameworks. The primary
users are SDK consumers who want to run agents locally and deploy them as Foundry-hosted
containers. Work is “done” when adapters faithfully translate framework execution into
Responses API-compatible outputs and the packages pass their expected tests and samples.

**Behavioral/policy rules live in `AGENTS.md`.** This document is architecture + repo map + doc index.

## 🎯 Goals / Non-goals
Goals:
- Keep a stable architecture snapshot and repo map for fast onboarding.
- Document key request/response flows, including streaming.
- Clarify the development workflow and testing expectations for AgentServer packages.

Non-goals:
- Detailed API documentation (belongs in package docs and docstrings).
- Per-initiative plans (belong in `TASK.md` or a dedicated plan file).
- Speculative refactors (align with KISS/YAGNI in `AGENTS.md`).

## 🧩 Architecture (snapshot)
### 🏗️ Project Structure
- **azure-ai-agentserver-core**: Core library
- Runtime/context
- HTTP gateway
- Foundry integrations
- Responses API protocol (current)
- **azure-ai-agentserver-agentframework**: adapters for Agent Framework agents/workflows,
thread and checkpoint persistence.
- **azure-ai-agentserver-langgraph**: adapter and converters for LangGraph agents and
Response API events.

### Current vs target
- Current: OpenAI Responses API protocol lives in `azure-ai-agentserver-core` alongside
core runtime and HTTP gateway code; framework adapters layer on top.
- Target (planned, not fully implemented):
- Core layer: app/runtime/context, foundry integrations (tools, checkpointing), HTTP gateway
- Protocol layer: Responses API in its own package
- Framework layer: adapters (agentframework, langgraph, other frameworks)

### Key flows
- Request path: `/runs` or `/responses` → `AgentRunContext` → agent execution → Responses
API payload.
- Streaming path: generator/async generator → SSE event stream.
- Framework adapter path: framework input → converter → Response API output (streaming
or non-streaming).
- Tools path: Foundry tool runtime invoked via core `tools/runtime` APIs.

## 🗺️ Repo map
- `azure-ai-agentserver-core`: Core library (runtime/context, HTTP gateway, Foundry integrations,
Responses API protocol today).
- `azure-ai-agentserver-agentframework`: Agent Framework adapter.
- `azure-ai-agentserver-langgraph`: LangGraph adapter.
- Core runtime and models: `azure-ai-agentserver-core/azure/ai/agentserver/core/`
- Agent Framework adapter: `azure-ai-agentserver-agentframework/azure/ai/agentserver/agentframework/`
- LangGraph adapter: `azure-ai-agentserver-langgraph/azure/ai/agentserver/langgraph/`
- Samples: `azure-ai-agentserver-*/samples/`
- Tests: `azure-ai-agentserver-*/tests/`
- Package docs (Sphinx inputs): `azure-ai-agentserver-*/doc/`
- Repo-wide guidance: `CONTRIBUTING.md`, `doc/dev/tests.md`, `doc/eng_sys_checks.md`

## 📚 Doc index
### **Read repo-wide guidance**:
- `CONTRIBUTING.md`
- `doc/dev/tests.md`
- `doc/eng_sys_checks.md`

### **Read the package READMEs**:
- `sdk/agentserver/azure-ai-agentserver-core/README.md`
- `sdk/agentserver/azure-ai-agentserver-agentframework/README.md`
- `sdk/agentserver/azure-ai-agentserver-langgraph/README.md`

### “If you need X, look at Y”
- Enable/disable checks for a package → that package `pyproject.toml` → `[tool.azure-sdk-build]`
- How to run tests / live-recorded tests → `doc/dev/tests.md`
- Engineering system checks / gates → `doc/eng_sys_checks.md`
- Adapter conversion behavior → the relevant adapter package + its tests + samples

## ✅ Testing strategy
- Unit/integration tests live in each package’s `tests/` directory.
- Samples are part of validation via the `samples` tox environment.
- For live/recorded testing patterns, follow `doc/dev/tests.md`.

## 🚀 Rollout / migrations
- Preserve public API stability and follow Azure SDK release policy.
- Do not modify generated code (see paths in `AGENTS.md`).
- CI checks are controlled per package in `pyproject.toml` under
`[tool.azure-sdk-build]`.

## ⚠️ Risks / edge cases
- Streaming event ordering and keep-alive behavior.
- Credential handling (async credentials and adapters).
- Response API schema compatibility across adapters.
- Tool invocation failures and error surfacing.

## 📌 Progress
See `TASK.md` for active work items; no checklists here.
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# Release History


## 1.0.0b2 (Unreleased)

### Other Changes

- To be updated


## 1.0.0b1 (2025-11-07)

### Features Added
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ classifiers = [
keywords = ["azure", "azure sdk"]

dependencies = [
"azure-ai-agentserver-core",
"azure-ai-agentserver-core==1.0.0b1",
"agent-framework-azure-ai==1.0.0b251007",
"agent-framework-core==1.0.0b251007",
"opentelemetry-exporter-otlp-proto-grpc>=1.36.0",
Expand Down Expand Up @@ -63,4 +63,5 @@ pyright = false
verifytypes = false # incompatible python version for -core
verify_keywords = false
mindependency = false # depends on -core package
whl_no_aio = false
whl_no_aio = false
mypy = false
Loading
Loading