# AI Agents for Beginners — Administrator & Developer Guide

## 1. Architecture Overview

AI Agents for Beginners is a 16-lesson educational curriculum from Microsoft that teaches AI agent development through structured lessons and runnable code samples. The repository is not a standalone application — it is a course package containing markdown content, Jupyter notebooks, and standalone code samples in Python and C# (.NET) that demonstrate agent patterns using the Microsoft Agent Framework (MAF).

### System Architecture

```text
ai-agents-for-beginners/
├── 00-course-setup/              Lesson 00: setup guide + Azure Search C# sample
├── 01-intro-to-ai-agents/        Lesson 01: intro + code_samples/
│   └── code_samples/                 01-dotnet-agent-framework.cs
├── 02-explore-agentic-frameworks/  Lesson 02: frameworks + code_samples/
├── 03-agentic-design-patterns/   Lesson 03: design patterns + code_samples/
├── 04-tool-use/                  Lesson 04: tool use + code_samples/ + tests
├── 05-agentic-rag/               Lesson 05: RAG + code_samples/
├── 06-building-trustworthy-agents/ Lesson 06: trust + code_samples/
├── 07-planning-design/           Lesson 07: planning + code_samples/
├── 08-multi-agent/               Lesson 08: multi-agent + code_samples/ + solution/
├── 09-metacognition/             Lesson 09: metacognition + code_samples/
├── 10-ai-agents-production/      Lesson 10: production + code_samples/
├── 11-agentic-protocols/         Lesson 11: MCP protocols + code_samples/
├── 12-context-engineering/       Lesson 12: context engineering + code_samples/
├── 13-agent-memory/              Lesson 13: agent memory
├── 14-microsoft-agent-framework/ Lesson 14: MAF deep dive + code-samples/
├── 15-browser-use/               Lesson 15: browser use
├── translations/                 40+ language translations
├── translated_images/            Localized images
├── requirements.txt              Python dependencies
├── global.json                   .NET SDK version pin
└── .env.example                  Environment variable template
```

### Component Inventory

| Component | Path | Role |
|-----------|------|------|
| Lesson READMEs | `{NN}-{topic}/README.md` | Conceptual teaching material |
| Python notebooks | `{NN}-{topic}/code_samples/*-python-agent-framework.ipynb` | Interactive Python exercises |
| C# samples | `{NN}-{topic}/code_samples/*-dotnet-agent-framework.cs` | Standalone C# demonstrations |
| MCP server | `11-agentic-protocols/code_samples/mcp-agents/server/` | Resumable MCP server with agent tools |
| MCP client | `11-agentic-protocols/code_samples/mcp-agents/client/` | Interactive host application |
| Event store | `11-agentic-protocols/code_samples/mcp-agents/server/event_store.py` | Session resumption storage |
| GitHub MCP app | `11-agentic-protocols/code_samples/github-mcp/app.py` | Chainlit + MAF multi-agent workflow |
| Hotel booking workflow | `14-microsoft-agent-framework/code-samples/hotel_booking_workflow_sample.py` | Conditional workflow demonstration |
| Azure Search setup | `00-course-setup/AzureSearch.cs` | Index creation and document upload |
| Translations | `translations/{lang}/` | Localized lesson content |
| Translated images | `translated_images/{lang}/` | Localized screenshots and diagrams |

### Technology Stack

| Layer | Technology | Version/Details |
|-------|-----------|-----------------|
| Agent Framework | Microsoft Agent Framework (MAF) | `agent-framework` (Python), `Microsoft.Agents.AI` (NuGet) |
| AI Services | Azure AI Foundry (Agent Service v2) | Responses API |
| AI Models | GPT-4o, GPT-4o-mini | Via Azure AI Foundry, GitHub Models, OpenAI, MiniMax |
| Protocol | Model Context Protocol (MCP) | `mcp[cli]` with StreamableHTTP transport |
| Chat UI | Chainlit | For Lesson 11 GitHub MCP sample |
| Search | Azure AI Search | For Lesson 5 (RAG) and Lesson 11 |
| Auth | Azure CLI (`AzureCliCredential`) | Keyless authentication |
| Python | 3.12+ | Virtual environment recommended |
| .NET | 10.0+ SDK | Inline `#:package` NuGet references |
| A2A | Agent-to-Agent SDK | `a2a-sdk` |

> [!NOTE]
> The repository uses `AzureCliCredential` for authentication throughout, avoiding API key management. This is a deliberate architectural choice aligned with Microsoft's keyless connection best practices.

### Data Flow: Typical Lesson Execution

```text
User → Jupyter Notebook / .cs file
  → Load .env (dotenv)
  → AzureCliCredential (az login session)
  → Azure AI Foundry Agent Service (or GitHub Models / OpenAI / MiniMax)
  → Agent executes with tools
  → Streaming response to user
```

For multi-agent workflows (Lessons 08, 14):

```text
User Input → WorkflowBuilder
  → Agent A (start executor)
  → Edge → Agent B (reviewer / next stage)
  → [Optional: conditional routing]
  → Final output streamed to user
```

For MCP-based agent communication (Lesson 11):

```text
User → Host (MCP Client)
  → MCP Server (StreamableHTTP)
  → Agent Tool (travel_agent / research_agent)
  → Progress notifications → Client
  → Elicitation / Sampling (mid-execution interaction)
  → EventStore (session resumption)
  → Final result
```

## 2. System Requirements

| Requirement | Minimum | Recommended |
|-------------|---------|-------------|
| Python | 3.12 | 3.12+ |
| .NET SDK | 10.0 | 10.0+ |
| Azure CLI | Latest | Latest |
| Git | 2.25 | Latest |
| OS | Windows / macOS / Linux | Any |
| Disk space | ~500 MB (sparse) | ~3 GB (full clone) |
| Azure Subscription | Required | With AI Foundry access |
| Network | Internet access | For Azure services and model API calls |

### Python Dependencies (from `requirements.txt`)

| Package | Purpose |
|---------|---------|
| `azure-ai-inference` | Azure AI model inference |
| `azure-ai-projects` | Azure AI Foundry project management |
| `azure-identity` | Azure authentication (`AzureCliCredential`) |
| `azure-search-documents` | Azure AI Search (Lesson 5, 11) |
| `agent-framework` | Microsoft Agent Framework |
| `a2a-sdk` | Agent-to-Agent protocol SDK |
| `mcp[cli]` | Model Context Protocol with CLI tools |
| `openai` | OpenAI API client |
| `httpx` | HTTP client |
| `ipykernel` | Jupyter notebook kernel |
| `nest-asyncio` | Nested async event loop support |
| `numpy` | Numerical operations |
| `pandas` | Data manipulation |
| `pillow` | Image processing |
| `python-dotenv` | `.env` file loading |
| `uvicorn` | ASGI server (MCP server) |

### .NET NuGet Dependencies (per sample)

| Package | Version | Used In |
|---------|---------|---------|
| `Microsoft.Extensions.AI` | 10.4.1 / 9.9.1 | Lessons 01-08 |
| `Microsoft.Extensions.AI.OpenAI` | 10.4.1+ | Lessons 01-04 |
| `Microsoft.Agents.AI.OpenAI` | 1.1.0 / 1.0.0-preview | Lessons 01-08 |
| `Microsoft.Agents.AI` | 1.0.0-preview | Lessons 05-08 |
| `Microsoft.Agents.AI.Workflows` | 1.0.0-preview | Lesson 08 |
| `Azure.AI.Agents.Persistent` | 1.2.0-beta | Lessons 05, 08 |
| `Azure.Identity` | 1.15.0 | Lessons 05, 08 |
| `DotNetEnv` | 3.1.1 | Lessons 05, 07, 08 |
| `OpenTelemetry.Api` | 1.12.0 | Lesson 08 |
| `System.Linq.Async` | 6.0.3 | Lessons 05, 08 |

> [!IMPORTANT]
> The `global.json` at the repository root pins the .NET SDK to version `10.0.100` with `rollForward: latestFeature` and `allowPrerelease: false`. This ensures consistent behavior across environments.

## 3. Configuration Reference

### Environment Variables — Complete Reference

| Variable | Type | Default | Required | Description | Used In |
|----------|------|---------|----------|-------------|---------|
| `AZURE_AI_PROJECT_ENDPOINT` | string | — | Yes | Azure AI Foundry project endpoint URL | All Azure notebooks |
| `AZURE_AI_MODEL_DEPLOYMENT_NAME` | string | `gpt-4.1-mini` | Yes | Model deployment name in Foundry | All Azure notebooks |
| `AZURE_SEARCH_SERVICE_ENDPOINT` | string | — | Lesson 5, 11 | Azure AI Search service URL | RAG, MCP GitHub app |
| `AZURE_SEARCH_API_KEY` | string | — | Lesson 5, 11 | Azure AI Search admin API key | RAG, MCP GitHub app |
| `GITHUB_TOKEN` | string | — | Lessons 6, 8, C# | GitHub personal access token | GitHub Models provider |
| `GITHUB_ENDPOINT` | string | `https://models.inference.ai.azure.com` | No | GitHub Models API endpoint | GitHub Models provider |
| `GITHUB_MODEL_ID` | string | `gpt-4o-mini` / `gpt-4o` | No | Model name for GitHub Models | GitHub Models provider |
| `GH_ENDPOINT` | string | `https://models.github.ai/inference` | No | C# sample GitHub Models endpoint | C# Lessons 01-04 |
| `GH_MODEL_ID` | string | `openai/gpt-5-mini` | No | C# sample model ID | C# Lessons 01-04 |
| `GH_TOKEN` | string | — | C# samples | C# sample GitHub token | C# Lessons 01-04 |
| `MINIMAX_API_KEY` | string | — | No | MiniMax API key | Lesson 14 |
| `MINIMAX_BASE_URL` | string | `https://api.minimax.io/v1` | No | MiniMax API endpoint | Lesson 14 |
| `MINIMAX_MODEL_ID` | string | `MiniMax-M2.7` | No | MiniMax model name | Lesson 14 |
| `OPENAI_API_KEY` | string | — | No | OpenAI API key (fallback provider) | Lesson 14 |

> [!WARNING]
> The C# samples (Lessons 01-04) use `GH_ENDPOINT`, `GH_MODEL_ID`, and `GH_TOKEN` with different defaults than the Python samples' `GITHUB_ENDPOINT`, `GITHUB_MODEL_ID`, and `GITHUB_TOKEN`. These are separate variable sets — setting one does not configure the other.

### Configuration Files

| File | Format | Location | Purpose |
|------|--------|----------|---------|
| `.env.example` | dotenv | Repository root | Template for environment variables |
| `.env` | dotenv | Repository root (gitignored) | Active environment configuration |
| `global.json` | JSON | Repository root | .NET SDK version pin |
| `requirements.txt` | pip | Repository root | Python dependency specification |

### `.env.example` Structure

```text
AZURE_AI_PROJECT_ENDPOINT=https://<your-project>.services.ai.azure.com/api/projects/<your-project-id>
AZURE_AI_MODEL_DEPLOYMENT_NAME=gpt-4o
```

### `global.json`

```json
{
  "sdk": {
    "version": "10.0.100",
    "rollForward": "latestFeature",
    "allowPrerelease": false
  }
}
```

> [!TIP]
> The `rollForward: latestFeature` setting allows using newer patch versions of the 10.0 SDK without updating `global.json`.

## 4. Deployment & Scaling

This repository is an educational course, not a deployable application. However, two components within it can be deployed independently:

### MCP Server Deployment (Lesson 11)

The resumable MCP server at `11-agentic-protocols/code_samples/mcp-agents/server/` can be run as a standalone service:

```bash
python -m server.server --port 8006
```

| Flag | Default | Description |
|------|---------|-------------|
| `--port` | `8006` | Port to listen on |
| `--no-event-store` | `false` | Disable event store (disables session resumption) |

The server uses Starlette + Uvicorn with these configuration defaults:

```python
config = uvicorn.Config(
    app=app,
    host="127.0.0.1",
    port=port,
    log_level="info",
    limit_concurrency=10,
    timeout_keep_alive=30,
    access_log=True,
)
```

Security settings restrict access to localhost:

```python
security_settings = TransportSecuritySettings(
    allowed_hosts=["127.0.0.1:*", "localhost:*"],
    allowed_origins=["http://127.0.0.1:*", "http://localhost:*"]
)
```

> [!CAUTION]
> The MCP server's `TransportSecuritySettings` only allows connections from `127.0.0.1` and `localhost`. To expose it to other hosts, you must modify the `allowed_hosts` and `allowed_origins` in `server.py`. Do this only in secure, controlled environments.

### Chainlit Application (Lesson 11)

The GitHub MCP app at `11-agentic-protocols/code_samples/github-mcp/app.py` is a Chainlit-based web application:

```bash
chainlit run app.py
```

This application requires:
- Azure AI Foundry credentials (via `az login`)
- Azure AI Search credentials (`AZURE_SEARCH_SERVICE_ENDPOINT`, `AZURE_SEARCH_API_KEY`)
- An MCP server configured in Chainlit's MCP settings

### GitHub Codespaces

The repository supports GitHub Codespaces for zero-install cloud development environments. Create a codespace directly from the GitHub repository page.

## 5. Operations

### Repository Maintenance

**Keeping lessons updated:** Each lesson is self-contained in its directory. To update a lesson, modify the `README.md` and/or `code_samples/` within that lesson's directory.

**Translation pipeline:** The `translations/` directory contains lesson content in 40+ languages. The `translated_images/` directory contains localized screenshots. These are maintained by an automated translation pipeline.

> [!NOTE]
> The translation infrastructure generates one translated README per language per lesson. Each translation directory mirrors the English lesson structure but with localized content and image references.

### Event Store Management (MCP Server)

The MCP server supports two event store implementations:

**`SimpleEventStore`** (in-memory, default):
- Events stored in a Python list
- Lost on server restart
- Suitable for development and testing

**`PersistentEventStore`** (SQLite):
- Events stored in `events.db`
- Survives server restarts
- Uses `check_same_thread=False` for async compatibility
- Schema: `CREATE TABLE events (id INTEGER PRIMARY KEY AUTOINCREMENT, stream_id TEXT NOT NULL, message TEXT NOT NULL)`

> [!TIP]
> For production-like testing of session resumption, use the `PersistentEventStore`. The `SimpleEventStore` is fine for quick development iterations but won't survive server restarts.

### Azure AI Search Index Management

Lesson 11's GitHub MCP app creates and manages an Azure AI Search index named `event-descriptions`:

- Index fields: `id` (String, key), `content` (String, searchable)
- On startup, the app checks if the index exists and creates it if not
- Documents are loaded from `event-descriptions.md`, split by `---` delimiter
- Existing documents are cleared and re-uploaded on each run

## 6. Performance

### Model Provider Comparison

| Provider | Latency | Context Window | Cost Model |
|----------|---------|----------------|------------|
| Azure AI Foundry | Low (Azure network) | Model-dependent | Azure pricing |
| GitHub Models | Moderate | Model-dependent | Free tier available |
| MiniMax | Moderate | Up to 204K tokens | MiniMax pricing |
| OpenAI | Moderate | Model-dependent | OpenAI pricing |

### MCP Server Performance Characteristics

The MCP server is configured for educational use:

- `limit_concurrency=10` — maximum 10 concurrent connections
- `timeout_keep_alive=30` — 30-second keep-alive timeout
- Agent tool steps use `anyio.sleep(2)` — 2-second delay between steps (simulated work)
- Long-running agent: 50 steps × 2 seconds = ~100 seconds total

> [!NOTE]
> The sleep delays in agent tools are intentional for demonstration purposes. In a production system, these would be replaced with actual computation.

## 7. Security

### Authentication Model

The course uses `AzureCliCredential` exclusively — no API keys are required for Azure authentication. This follows Microsoft's keyless connection best practices.

| Service | Auth Method | Credential Source |
|---------|-------------|-------------------|
| Azure AI Foundry | `AzureCliCredential` | `az login` session |
| Azure AI Search | API key | `.env` file |
| GitHub Models | Personal access token | `.env` file |
| MiniMax | API key | `.env` file |
| OpenAI | API key | `.env` file |

> [!WARNING]
> While Azure AI Foundry uses keyless auth, Azure AI Search and alternative providers still require API keys stored in the `.env` file. Never commit `.env` to version control.

### MCP Server Security

The MCP server enforces transport-level security:

```python
security_settings = TransportSecuritySettings(
    allowed_hosts=["127.0.0.1:*", "localhost:*"],
    allowed_origins=["http://127.0.0.1:*", "http://localhost:*"]
)
```

This restricts all connections to localhost. The server does not implement authentication — it assumes a trusted local environment.

### Secrets Management

| Secret | Storage | Risk if Exposed |
|--------|---------|-----------------|
| `AZURE_SEARCH_API_KEY` | `.env` | Azure Search index read/write access |
| `GITHUB_TOKEN` | `.env` | GitHub API access (scope-dependent) |
| `GH_TOKEN` | `.env` | Same as GITHUB_TOKEN, used in C# samples |
| `MINIMAX_API_KEY` | `.env` | MiniMax API access and billing |
| `OPENAI_API_KEY` | `.env` | OpenAI API access and billing |

> [!CAUTION]
> The `.env.example` file does not include placeholder values for API keys. Always verify that `.env` is listed in `.gitignore` before committing.

## 8. Developer Internals

### Repository Structure

```text
ai-agents-for-beginners/
├── 00-course-setup/                    Setup guide
│   └── AzureSearch.cs                  Azure Search index creation (C#)
├── 01-intro-to-ai-agents/             Introduction lesson
│   └── code_samples/
│       └── 01-dotnet-agent-framework.cs  Simple agent with tool
├── 02-explore-agentic-frameworks/      Framework exploration
│   └── code_samples/
│       └── 02-dotnet-agent-framework.cs  Multi-turn agent with threads
├── 03-agentic-design-patterns/         Design principles
│   └── code_samples/
│       └── 03-dotnet-agent-framework.cs  Transparency/control/consistency demo
├── 04-tool-use/                        Tool calling patterns
│   └── code_samples/
│       ├── 04-dotnet-agent-framework.cs  Multi-tool composition
│       └── test_demo_plugins.py          Plugin unit tests
├── 05-agentic-rag/                     RAG pattern
│   └── code_samples/
│       └── 05-dotnet-agent-framework.cs  File search with vector store
├── 06-building-trustworthy-agents/     Trust and safety
├── 07-planning-design/                 Task decomposition
│   └── code_samples/
│       └── 07-dotnet-agent-framework.cs  Structured output planning
├── 08-multi-agent/                     Multi-agent systems
│   └── code_samples/
│       ├── 08-dotnet-agent-framework.cs  WorkflowBuilder sequential
│       └── workflows-agent-framework/    Full workflow tutorial
├── 09-metacognition/                   Agent self-reflection
├── 10-ai-agents-production/            Production considerations
├── 11-agentic-protocols/               MCP protocol
│   └── code_samples/
│       ├── github-mcp/app.py             Chainlit multi-agent app
│       └── mcp-agents/
│           ├── server/server.py          Resumable MCP server
│           ├── server/event_store.py     Event store implementations
│           └── client/client.py          Interactive MCP client
├── 12-context-engineering/             Context management
├── 13-agent-memory/                    Memory patterns
├── 14-microsoft-agent-framework/       MAF deep dive
│   └── code-samples/
│       └── hotel_booking_workflow_sample.py  Conditional workflow
├── 15-browser-use/                     Browser automation
├── translations/                       40+ language translations
├── translated_images/                  Localized images
├── requirements.txt                    Python dependencies
├── global.json                         .NET SDK config
└── .env.example                        Env var template
```

### Module Reference

#### `11-agentic-protocols/code_samples/github-mcp/app.py`

The most complex code sample in the repository. A Chainlit-based multi-agent application that demonstrates MCP integration with Azure AI Foundry.

**Key components:**

| Function/Decorator | Purpose |
|---------------------|---------|
| `search_events(query)` | RAG tool — searches Azure AI Search and Devpost API for events |
| `flatten(xss)` | Utility — flattens nested lists |
| `@cl.on_mcp_connect` / `on_mcp()` | MCP lifecycle — handles MCP server connection, discovers tools |
| `@cl.step` / `call_tool()` | Tool execution — routes MCP tool calls to the correct server |
| `@cl.on_chat_start` / `on_chat_start()` | Session init — creates 3 agents (GitHub, Hackathon, Events), builds sequential workflow |
| `@cl.on_chat_end` / `on_chat_end()` | Session cleanup (no-op) |
| `route_user_input(user_input)` | Input routing — regex-based selection of which agents to invoke |
| `@cl.on_message` / `on_message()` | Message handler — orchestrates single-agent or multi-agent workflow execution |

**Agent definitions:**

| Agent | Role | Capabilities |
|-------|------|-------------|
| `GithubAgent` | Analyzes GitHub repositories by username | Uses MCP tools for GitHub API access |
| `HackathonAgent` | Recommends hackathon project ideas | Based on user's GitHub profile analysis |
| `EventsAgent` | Recommends tech events | Uses `search_events` tool for Azure Search + Devpost |

**Workflow pattern:** Sequential — GitHub → Hackathon → Events, built with `WorkflowBuilder`.

#### `11-agentic-protocols/code_samples/mcp-agents/server/server.py`

Resumable MCP server implementing the StreamableHTTP transport with three agent tools.

**Classes:**

| Class | Parent | Purpose |
|-------|--------|---------|
| `PriceConfirmationSchema` | `BaseModel` | Pydantic schema for elicitation — price confirmation with notes |
| `ResumableServer` | `Server` (MCP) | Server with tool handlers for travel, research, and long-running agents |

**Tools exposed:**

| Tool | Parameters | Features Demonstrated |
|------|-----------|----------------------|
| `travel_agent` | `destination` (default: "Paris") | Progress notifications, elicitation (price confirmation), cancellation |
| `research_agent` | `topic` (default: "AI trends") | Progress notifications, sampling (AI-generated summary) |
| `long_running_agent` | None | 50 steps × 2s, log messages, resumption testing |

**Key functions:**

| Function | Purpose |
|----------|---------|
| `create_server_app(event_store)` | Creates Starlette ASGI app with `StreamableHTTPSessionManager` |
| `run_server(port, with_event_store)` | Starts Uvicorn server with configurable port and event store |
| `main()` | CLI entry point with `--port` and `--no-event-store` flags |

#### `11-agentic-protocols/code_samples/mcp-agents/server/event_store.py`

Two event store implementations for MCP session resumption.

**`SimpleEventStore`** (in-memory):

| Method | Purpose |
|--------|---------|
| `store_event(stream_id, message)` | Appends event to list, returns incremented ID |
| `replay_events_after(last_event_id, callback)` | Replays events after a given ID via callback |
| `get_event_count()` | Returns total stored events |
| `clear_events()` | Clears all events and resets counter |

**`PersistentEventStore`** (SQLite):

| Method | Purpose |
|--------|---------|
| `store_event(stream_id, message)` | Inserts into SQLite via `asyncio.to_thread` |
| `replay_events_after(last_event_id, callback)` | Fetches and replays events for the same stream |
| `_create_table()` | Creates `events` table on init |
| `close()` | Closes SQLite connection with error handling |
| Context manager (`__enter__`/`__exit__`) | Supports `with` statement for resource cleanup |

#### `14-microsoft-agent-framework/code-samples/hotel_booking_workflow_sample.py`

Conditional workflow demonstration with three Pydantic models and routing logic.

**Classes:**

| Class | Parent | Fields |
|-------|--------|--------|
| `BookingCheckResult` | `BaseModel` | `destination`, `has_availability`, `message` |
| `AlternativeResult` | `BaseModel` | `alternative_destination`, `reason` |
| `BookingConfirmation` | `BaseModel` | `destination`, `action`, `message` |

**Functions:**

| Function | Purpose |
|----------|---------|
| `hotel_booking(destination)` | `@ai_function` — simulates hotel availability (Stockholm, Seattle, Tokyo, London, Amsterdam have rooms) |
| `has_availability_condition(message)` | Routing condition — returns `True` when rooms are available |
| `no_availability_condition(message)` | Routing condition — returns `True` when no rooms available |
| `display_result(response, ctx)` | `@executor` — yields final workflow output |
| `main()` | Builds and runs conditional workflow with two test cases |

**Workflow graph:**

```text
User Input → availability_agent
  ├── [has rooms] → booking_agent → display_result
  └── [no rooms] → alternative_agent → display_result
```

**Provider auto-detection order:** MiniMax → GitHub Models → OpenAI (based on which API key env var is set).

#### C# Samples (Lessons 01-08)

Each C# sample follows a consistent pattern:

1. Inline `#:package` NuGet dependency declarations
2. Environment variable loading (`GH_ENDPOINT`, `GH_MODEL_ID`, `GH_TOKEN` or `GITHUB_*` variants)
3. `OpenAIClient` creation pointed at GitHub Models endpoint
4. `AIAgent` creation via fluent API (`.AsAIAgent()` or `.CreateAIAgent()`)
5. Tool registration via `AIFunctionFactory.Create()`
6. Streaming execution via `RunStreamingAsync()`

**Key API patterns:**

```csharp
// Lesson 01: Simple agent
AIAgent agent = openAIClient
    .GetChatClient(model_id)
    .AsAIAgent(instructions: "...", tools: [...]);

// Lesson 02+: Agent with named options and thread
AIAgent agent = openAIClient
    .GetChatClient(model_id)
    .AsIChatClient()
    .CreateAIAgent(name: "...", instructions: "...", tools: [...]);
AgentThread thread = agent.GetNewThread();

// Lesson 07: Structured output
ChatClientAgentOptions options = new(name: "...", instructions: "...") {
    ChatOptions = new() {
        ResponseFormat = ChatResponseFormatJson.ForJsonSchema(
            schema: AIJsonUtilities.CreateJsonSchema(typeof(TravelPlan)),
            schemaName: "TravelPlan")
    }
};

// Lesson 08: Multi-agent workflow
var workflow = new WorkflowBuilder(frontdeskAgent)
    .AddEdge(frontdeskAgent, reviewerAgent)
    .Build();
```

#### `04-tool-use/code_samples/test_demo_plugins.py`

Unit tests for the tool use lesson's Python plugins:

| Test | Validates |
|------|-----------|
| `test_calculator_add()` | `CalculatorPlugin.add(5, 7) == 12` |
| `test_calculator_subtract()` | `CalculatorPlugin.subtract(10, 4) == 6` |
| `test_time_plugin()` | `TimePlugin.get_current_time()` returns 19-char datetime string |

> [!NOTE]
> These tests import from `demo_tool_agent` which is a Python module defined in the corresponding notebook. The test file contains a typo (`AssertionError` instead of `AssertionError`) that would prevent proper exception handling — this is a non-critical issue in educational sample code.

### Code Patterns and Conventions

**Agent creation pattern (Python — MAF):**
```python
from agent_framework import WorkflowBuilder
from agent_framework.openai import OpenAIChatClient

chat_client = OpenAIChatClient(base_url=endpoint, api_key=token, model_id=model)
agent = chat_client.create_agent(instructions="...", name="...", tools=[...])
```

**Agent creation pattern (Python — Azure AI Foundry):**
```python
from agent_framework.azure import AzureAIProjectAgentProvider
from azure.identity import AzureCliCredential

provider = AzureAIProjectAgentProvider(credential=AzureCliCredential())
agent = await provider.create_agent(name="...", instructions="...")
```

**Workflow patterns:**
- **Sequential:** `WorkflowBuilder().set_start_executor(a).add_edge(a, b).build()`
- **Concurrent:** `ConcurrentBuilder().participants([a, b]).build()`
- **Conditional:** `.add_edge(a, b, condition=condition_func)`
- **Fan-out/Fan-in (C#):** `.AddFanOutEdge()` / `.AddFanInEdge()`

**Environment variable loading:** All samples use `python-dotenv` (`load_dotenv()`) or `DotNetEnv` (`Env.Load()`) to load `.env` files, typically from the repository root via relative path `../../../.env`.

**Structured output:** Pydantic `BaseModel` subclasses for Python, `JsonPropertyName`-annotated C# classes for .NET, passed as `response_format` to agent configuration.

### Testing Strategy

The repository has minimal automated testing:

- `04-tool-use/code_samples/test_demo_plugins.py` — 3 unit tests for calculator and time plugins
- No integration test suite
- No CI/CD pipeline configuration visible in the briefing

Testing is primarily manual: run the notebook, verify the output matches expected behavior.

### Potential Improvements

- **Automated testing:** Add pytest or unittest suites for each lesson's code samples
- **CI pipeline:** Add GitHub Actions to validate that all samples at least import correctly
- **Dependency pinning:** `requirements.txt` lacks version pins — could cause breakage as packages update
- **Consistent env var naming:** Python samples use `GITHUB_*` while C# uses `GH_*` — could be unified
- **Error handling:** Most samples use broad `except Exception` catches — could be more specific
- **The `test_demo_plugins.py` typo:** `AssertionError` should be `AssertionError` (though both resolve to the same built-in)

### Contributing

The repository is open source under MIT license and accepts community contributions. Existing community engagement (from GitHub issues):

- Issue #503: Content contribution for a new lesson on securing AI agents with cryptographic receipts
- Issue #517: Integration proposal for agentic commerce
- Issue #525: Typo fix for broken README link (closed, fixed)
- Issue #518: Typo fix in Lesson 05 image (closed)
- Issue #491: Missing Chinese translation for agent memory module (closed)
- Issue #479: Resource suggestion for a multi-agent CLI runtime (closed)

## 9. Integration Points

### Azure AI Foundry

Primary integration for model inference and agent services:

- **Endpoint:** Configured via `AZURE_AI_PROJECT_ENDPOINT`
- **Auth:** `AzureCliCredential` (no API keys)
- **Protocol:** Azure AI Agent Service v2 (Responses API)
- **SDK:** `azure-ai-projects`, `azure-ai-inference`

### Azure AI Search

Used for RAG (Lesson 5) and event search (Lesson 11):

- **Endpoint:** Configured via `AZURE_SEARCH_SERVICE_ENDPOINT`
- **Auth:** Admin API key via `AZURE_SEARCH_API_KEY`
- **SDK:** `azure-search-documents`
- **Index schema:** Simple key-value with `id` (String) and `content` (searchable String)

### GitHub Models

Alternative model provider used in Lessons 6, 8, and C# samples:

- **Endpoint:** `https://models.inference.ai.azure.com` (Python) or `https://models.github.ai/inference` (C#)
- **Auth:** Personal access token via `GITHUB_TOKEN` / `GH_TOKEN`
- **SDK:** OpenAI client library with custom endpoint

### MiniMax

OpenAI-compatible alternative provider for Lesson 14:

- **Endpoint:** `https://api.minimax.io/v1`
- **Auth:** API key via `MINIMAX_API_KEY`
- **Models:** `MiniMax-M2.7` (recommended), `MiniMax-M2.7-highspeed`
- **Feature:** Up to 204K token context window

### Model Context Protocol (MCP)

Lesson 11 implements MCP server and client for agent-to-agent communication:

- **Transport:** StreamableHTTP (Starlette + Uvicorn)
- **Features used:** Tool calls, progress notifications, log messages, elicitation, sampling, session resumption
- **Event store:** In-memory (`SimpleEventStore`) or SQLite (`PersistentEventStore`)
- **SDK:** `mcp[cli]`

### Chainlit

Chat UI framework for the GitHub MCP demo:

- **Entry point:** `app.py` with `@cl.on_chat_start`, `@cl.on_message`, `@cl.on_mcp_connect`
- **Features:** Streaming responses, tool step visualization, MCP server integration, user session management

### Devpost API

External API called by the `search_events` tool in Lesson 11:

- **Endpoint:** `https://devpost.com/api/hackathons?search={query}`
- **Method:** GET with 5-second timeout
- **Response:** JSON with `hackathons` array containing `title` and `url` fields
- **Purpose:** Supplements Azure AI Search results with live hackathon data

---

_Generated May 2026 from microsoft/ai-agents-for-beginners at dff1fab. AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it. Unofficial; not affiliated with or reviewed by the project._
