Files
Eduard van Valkenburg a2856d3b92 Python: restructure: Python samples into progressive 01-05 layout (#3862)
* restructure: Python samples into progressive 01-05 layout

- 01-get-started/: 6 numbered steps (hello agent → hosting)
- 02-agents/: all agent concept samples (tools, middleware, providers, etc.)
- 03-workflows/: ALL existing workflow samples preserved as-is
- 04-hosting/: azure-functions, durabletask, a2a
- 05-end-to-end/: demos, evaluation, hosted agents
- Old files moved to _to_delete/ for review
- Added AGENTS.md with structure documentation
- autogen-migration/ and semantic-kernel-migration/ preserved at root

* fix: switch to AzureOpenAI Foundry, fix CI failures

- Switch all 01-get-started samples to AzureOpenAIResponsesClient with
  Azure AI Foundry project endpoint (AZURE_AI_PROJECT_ENDPOINT +
  AZURE_OPENAI_RESPONSES_DEPLOYMENT_NAME + AzureCliCredential)
- Add _to_delete/ and 05-end-to-end/ to pyrightconfig.samples.json excludes
- Fix test paths in packages/ that referenced old getting_started/ dirs:
  durabletask conftest + streaming test, azurefunctions conftest,
  devui conftest + capture_messages + openai_sdk_integration
- Fix workflow_as_agent_human_in_the_loop.py import (sibling import)
- Update hosting READMEs and tool comment paths
- Replace root README.md with new structure overview
- Update AGENTS.md to document Azure OpenAI Foundry as default provider

* cleanup: remove _to_delete folder, copy resource files to active dirs

All files in _to_delete/ were either:
- Exact duplicates of files in the new structure (240 files)
- Same file with only comment path updates (100 files)
- One import-fix diff (workflow_as_agent_human_in_the_loop.py)
- One superseded minimal_sample.py

Resource files (sample.pdf, countries.json, employees.pdf, weather.json)
copied to 02-agents/sample_assets/ and 02-agents/resources/ since active
samples reference them.

* fix: address PR review comments, centralize resources, remove root duplicates

- Fix type annotation in 04_memory.py (string union -> proper types)
- Fix old sample paths in observability files
- Fix grammar/spelling in observability samples
- Move sample_assets/ and resources/ to shared/ folder
- Remove 8 duplicate observability files from 02-agents root
- Update resource path references in multimodal_input and provider samples

* fix: update broken links from old getting_started paths to new structure

- Update relative paths in READMEs: getting_started/ → 01-get-started/,
  02-agents/, 03-workflows/, 04-hosting/, 05-end-to-end/
- Fix absolute GitHub URLs in package READMEs
- Fix broken link in ollama package README

* fix: convert absolute GitHub URLs to relative paths for link checker

Absolute URLs to python/samples/ on main branch 404 until PR merges.
Converted to relative paths that linkspector can verify locally.

* fix: update link for handoff sample moved to orchestrations/

* fix: update chatkit-integration README path from demos/ to 05-end-to-end/

* fix: update broken links in orchestrations README to match flat directory structure
2026-02-12 17:36:36 +00:00

8.9 KiB

ChatKit Integration Sample with Weather Agent and Image Analysis

This sample demonstrates how to integrate Microsoft Agent Framework with OpenAI ChatKit. It provides a complete implementation of a weather assistant with interactive widget visualization, image analysis, and file upload support.

Features:

  • Weather information with interactive widgets
  • Image analysis using vision models
  • Current time queries
  • File upload with attachment storage
  • Chat interface with streaming responses
  • City selector widget with one-click weather

Architecture

graph TB
    subgraph Frontend["React Frontend (ChatKit UI)"]
        UI[ChatKit Components]
        Upload[File Upload]
    end

    subgraph Backend["FastAPI Server"]
        FastAPI[FastAPI Endpoints]

        subgraph ChatKit["WeatherChatKitServer"]
            Respond[respond method]
            Action[action method]
        end

        subgraph Stores["Data & Storage Layer"]
            SQLite[SQLiteStore<br/>Store Protocol]
            AttStore[FileBasedAttachmentStore<br/>AttachmentStore Protocol]
            DB[(SQLite DB<br/>chatkit_demo.db)]
            Files[/uploads directory/]
        end

        subgraph Integration["Agent Framework Integration"]
            Converter[ThreadItemConverter]
            Streamer[stream_agent_response]
            Agent[Agent]
        end

        Widgets[Widget Rendering<br/>render_weather_widget<br/>render_city_selector_widget]
    end

    subgraph Azure["Azure AI"]
        Foundry[GPT-5<br/>with Vision]
    end

    UI -->|HTTP POST /chatkit| FastAPI
    Upload -->|HTTP POST /upload/id| FastAPI

    FastAPI --> ChatKit

    ChatKit -->|save/load threads| SQLite
    ChatKit -->|save/load attachments| AttStore
    ChatKit -->|convert messages| Converter

    SQLite -.->|persist| DB
    AttStore -.->|save files| Files
    AttStore -.->|save metadata| SQLite

    Converter -->|Message array| Agent
    Agent -->|AgentResponseUpdate| Streamer
    Streamer -->|ThreadStreamEvent| ChatKit

    ChatKit --> Widgets
    Widgets -->|WidgetItem| ChatKit

    Agent <-->|Chat Completions API| Foundry

    ChatKit -->|ThreadStreamEvent| FastAPI
    FastAPI -->|SSE Stream| UI

    style ChatKit fill:#e1f5ff
    style Stores fill:#fff4e1
    style Integration fill:#f0e1ff
    style Azure fill:#e1ffe1

Server Implementation

The sample implements a ChatKit server using the ChatKitServer base class from the chatkit package:

Core Components:

  • WeatherChatKitServer: Custom ChatKit server implementation that:

    • Extends ChatKitServer[dict[str, Any]]
    • Uses Agent Framework's Agent with Azure OpenAI
    • Converts ChatKit messages to Agent Framework format using ThreadItemConverter
    • Streams responses back to ChatKit using stream_agent_response
    • Creates and streams interactive widgets after agent responses
  • SQLiteStore: Data persistence layer that:

    • Implements the Store[dict[str, Any]] protocol from ChatKit
    • Persists threads, messages, and attachment metadata in SQLite
    • Provides thread management and item history
    • Stores attachment metadata for the upload lifecycle
  • FileBasedAttachmentStore: File storage implementation that:

    • Implements the AttachmentStore[dict[str, Any]] protocol from ChatKit
    • Stores uploaded files on the local filesystem (in ./uploads directory)
    • Generates upload URLs for two-phase file upload
    • Saves attachment metadata to the data store for upload tracking
    • Provides preview URLs for images

Key Integration Points:

# Converting ChatKit messages to Agent Framework
converter = ThreadItemConverter(
    attachment_data_fetcher=self._fetch_attachment_data
)
agent_messages = await converter.to_agent_input(user_message_item)

# Running agent and streaming back to ChatKit
async for event in stream_agent_response(
    self.weather_agent.run(agent_messages, stream=True),
    thread_id=thread.id,
):
    yield event

# Streaming widgets
widget = render_weather_widget(weather_data)
async for event in stream_widget(thread_id=thread.id, widget=widget):
    yield event

Installation and Setup

Prerequisites

  • Python 3.10+
  • Node.js 18.18+ and npm 9+
  • Azure OpenAI service configured
  • Azure CLI for authentication (az login)

Network Requirements

Important: This sample uses the OpenAI ChatKit frontend, which requires internet connectivity to OpenAI services.

The frontend makes outbound requests to:

  • cdn.platform.openai.com - ChatKit UI library (required)
  • chatgpt.com - Configuration endpoint
  • api-js.mixpanel.com - Telemetry

This sample is not suitable for air-gapped or network-restricted environments. The ChatKit frontend library cannot be self-hosted. See Limitations for details.

Domain Key Configuration

For local development, the sample uses a default domain key (domain_pk_localhost_dev).

For production deployment:

  1. Register your domain at platform.openai.com

  2. Create a .env file in the frontend directory:

    VITE_CHATKIT_API_DOMAIN_KEY=your_domain_key_here
    

Backend Setup

  1. Install Python packages:
cd python/samples/05-end-to-end/chatkit-integration
pip install agent-framework-chatkit fastapi uvicorn azure-identity
  1. Configure Azure OpenAI:
export AZURE_OPENAI_ENDPOINT="https://your-resource.openai.azure.com/"
export AZURE_OPENAI_API_VERSION="2024-06-01"
export AZURE_OPENAI_CHAT_DEPLOYMENT_NAME="gpt-4o"
  1. Authenticate with Azure:
az login

Frontend Setup

Install the Node.js dependencies:

cd frontend
npm install

How to Run

Start the Backend Server

From the chatkit-integration directory:

python app.py

Or with auto-reload for development:

uvicorn app:app --host 127.0.0.1 --port 8001 --reload

The backend will start on http://localhost:8001

Start the Frontend Development Server

In a new terminal, from the frontend directory:

npm run dev

The frontend will start on http://localhost:5171

Access the Application

Open your browser and navigate to:

http://localhost:5171

You can now:

  • Ask about weather in any location (weather widgets display automatically)
  • Upload images for analysis using the attachment button
  • Get the current time
  • Ask to see available cities and click city buttons for instant weather

Project Structure

chatkit-integration/
├── app.py                    # FastAPI backend with ChatKitServer implementation
├── store.py                  # SQLiteStore implementation
├── attachment_store.py       # FileBasedAttachmentStore implementation
├── weather_widget.py         # Widget rendering functions
├── chatkit_demo.db          # SQLite database (auto-created)
├── uploads/                  # Uploaded files directory (auto-created)
└── frontend/
    ├── package.json
    ├── vite.config.ts
    ├── index.html
    └── src/
        ├── main.tsx
        └── App.tsx           # ChatKit UI integration

Configuration

You can customize the application by editing constants at the top of app.py:

# Server configuration
SERVER_HOST = "127.0.0.1"  # Bind to localhost only for security (local dev)
SERVER_PORT = 8001
SERVER_BASE_URL = f"http://localhost:{SERVER_PORT}"

# Database configuration
DATABASE_PATH = "chatkit_demo.db"

# File storage configuration
UPLOADS_DIRECTORY = "./uploads"

# User context
DEFAULT_USER_ID = "demo_user"

Sample Conversations

Try these example queries:

  • "What's the weather like in Tokyo?"
  • "Show me available cities" (displays interactive city selector)
  • "What's the current time?"
  • Upload an image and ask "What do you see in this image?"

Limitations

Air-Gapped / Regulated Environments

The ChatKit frontend (chatkit.js) is loaded from OpenAI's CDN and cannot be self-hosted. This means:

  • Not suitable for air-gapped environments where *.openai.com is blocked
  • Not suitable for regulated environments that prohibit external telemetry
  • Requires domain registration with OpenAI for production use

What you CAN self-host:

  • The Python backend (FastAPI server, ChatKitServer, stores)
  • The agent-framework-chatkit integration layer
  • Your LLM infrastructure (Azure OpenAI, local models, etc.)

What you CANNOT self-host:

  • The ChatKit frontend UI library

For more details, see:

Learn More