Skip to content

Commit c39845d

Browse files
Python: small fixes in foundry (#297)
* small fixes in foundry * other samples updated * make it optional * added instructions and response format to create agent * mypy fix * shortened main readme and improved python readme
1 parent 30fc2b6 commit c39845d

File tree

9 files changed

+416
-242
lines changed

9 files changed

+416
-242
lines changed

README.md

Lines changed: 24 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ Highlights
99
- Multimodal: Text, vision, and function calling
1010
- Cross-Platform: .NET and Python implementations
1111

12-
## Quick Install
12+
Below are the basics for each language implementation. For more details on python see [here](./python/README.md) and for .NET see [here](./dotnet/README.md).
13+
14+
## Python - Quick Install
1315

1416
```bash
1517
pip install agent-framework
@@ -25,13 +27,14 @@ Supported Platforms:
2527
- Python: 3.10+
2628
- OS: Windows, macOS, Linux
2729

28-
## 1. Setup API Keys
30+
## Python - 1. Setup API Keys
2931

3032
Set as environment variables, or create a .env file at your project root:
3133

3234
```bash
3335
OPENAI_API_KEY=sk-...
3436
OPENAI_CHAT_MODEL_ID=...
37+
OPENAI_RESPONSES_MODEL_ID=...
3538
...
3639
AZURE_OPENAI_API_KEY=...
3740
AZURE_OPENAI_ENDPOINT=...
@@ -56,66 +59,38 @@ chat_client = AzureChatClient(
5659

5760
See the following [setup guide](https://github.com/microsoft/agent-framework/tree/main/python/samples/getting_started) for more information.
5861

59-
## 2. Create a Simple Agent
62+
## Python - 2. Create a Simple Agent
6063

6164
Create agents and invoke them directly:
6265

6366
```python
6467
import asyncio
6568
from agent_framework import ChatClientAgent
66-
from agent_framework.openai import OpenAIChatClient
69+
from agent_framework.foundry import FoundryChatClient
6770

6871
async def main():
69-
agent = ChatClientAgent(
70-
chat_client=OpenAIChatClient(),
71-
instructions="""
72+
async with ChatClientAgent(
73+
chat_client=FoundryChatClient(),
74+
instructions="""These are the Three Laws of Robotics:
7275
1) A robot may not injure a human being...
7376
2) A robot must obey orders given it by human beings...
7477
3) A robot must protect its own existence...
7578
76-
Give me the TLDR in exactly 5 words.
79+
Respond concisely to the user's request.
80+
"""
81+
):
82+
result = await agent.run("Summarize the Three Laws of Robotics")
83+
print(result.text)
84+
"""
85+
Output:
86+
Protect humans, obey, self-preserve, prioritized.
7787
"""
78-
)
79-
80-
result = await agent.run("Summarize the Three Laws of Robotics")
81-
print(result)
82-
83-
asyncio.run(main())
84-
# Output: Protect humans, obey, self-preserve, prioritized.
85-
```
86-
87-
## 3. Directly Use Chat Clients (No Agent Required)
88-
89-
You can use the chat client classes directly for advanced workflows:
90-
91-
```python
92-
import asyncio
93-
from agent_framework.openai import OpenAIChatClient
94-
from agent_framework import ChatMessage, ChatRole
95-
96-
async def main():
97-
client = OpenAIChatClient()
98-
99-
messages = [
100-
ChatMessage(role=ChatRole.SYSTEM, text="You are a helpful assistant."),
101-
ChatMessage(role=ChatRole.USER, text="Write a haiku about Agent Framework.")
102-
]
103-
104-
response = await client.get_response(messages)
105-
print(response.messages[0].text)
106-
107-
"""
108-
Output:
109-
110-
Agents work in sync,
111-
Framework threads through each task—
112-
Code sparks collaboration.
113-
"""
11488

115-
asyncio.run(main())
89+
if __name__ == "__main__":
90+
asyncio.run(main())
11691
```
11792

118-
## 4. Build an Agent with Tools and Functions
93+
## Python - 3. Build an Agent with Tools
11994

12095
Enhance your agent with custom tools and function calling:
12196

@@ -125,7 +100,7 @@ from typing import Annotated
125100
from random import randint
126101
from pydantic import Field
127102
from agent_framework import ChatClientAgent
128-
from agent_framework.openai import OpenAIChatClient
103+
from agent_framework.openai import OpenAIResponsesClient
129104

130105

131106
def get_weather(
@@ -147,13 +122,13 @@ def get_menu_specials() -> str:
147122

148123
async def main():
149124
agent = ChatClientAgent(
150-
chat_client=OpenAIChatClient(),
125+
chat_client=OpenAIResponsesClient(),
151126
instructions="You are a helpful assistant that can provide weather and restaurant information.",
152127
tools=[get_weather, get_menu_specials]
153128
)
154129

155130
response = await agent.run("What's the weather in Amsterdam and what are today's specials?")
156-
print(response)
131+
print(response.text)
157132

158133
"""
159134
Output:
@@ -167,56 +142,6 @@ if __name__ == "__main__":
167142

168143
You can explore additional agent samples [here](https://github.com/microsoft/agent-framework/tree/main/python/samples/getting_started/agents).
169144

170-
## 5. Multi-Agent Orchestration
171-
172-
Coordinate multiple agents to collaborate on complex tasks using orchestration patterns:
173-
174-
```python
175-
import asyncio
176-
from agent_framework import ChatClientAgent
177-
from agent_framework.openai import OpenAIChatClient
178-
179-
180-
async def main():
181-
# Create specialized agents
182-
writer = ChatClientAgent(
183-
chat_client=OpenAIChatClient(),
184-
name="Writer",
185-
instructions="You are a creative content writer. Generate and refine slogans based on feedback."
186-
)
187-
188-
reviewer = ChatClientAgent(
189-
chat_client=OpenAIChatClient(),
190-
name="Reviewer",
191-
instructions="You are a critical reviewer. Provide detailed feedback on proposed slogans."
192-
)
193-
194-
# Sequential workflow: Writer creates, Reviewer provides feedback
195-
task = "Create a slogan for a new electric SUV that is affordable and fun to drive."
196-
197-
# Step 1: Writer creates initial slogan
198-
initial_result = await writer.run(task)
199-
print(f"Writer: {initial_result}")
200-
201-
# Step 2: Reviewer provides feedback
202-
feedback_request = f"Please review this slogan: {initial_result}"
203-
feedback = await reviewer.run(feedback_request)
204-
print(f"Reviewer: {feedback}")
205-
206-
# Step 3: Writer refines based on feedback
207-
refinement_request = f"Please refine this slogan based on the feedback: {initial_result}\nFeedback: {feedback}"
208-
final_result = await writer.run(refinement_request)
209-
print(f"Final Slogan: {final_result}")
210-
211-
# Example Output:
212-
# Writer: "Charge Forward: Affordable Adventure Awaits!"
213-
# Reviewer: "Good energy, but 'Charge Forward' is overused in EV marketing..."
214-
# Final Slogan: "Power Up Your Adventure: Premium Feel, Smart Price!"
215-
216-
if __name__ == "__main__":
217-
asyncio.run(main())
218-
```
219-
220145
**Note**: Advanced orchestration patterns like GroupChat, Sequential, and Concurrent orchestrations are coming soon.
221146

222147
## More Examples & Samples

python/DEV_SETUP.md

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ want to run the tests included.
66

77
## System setup
88

9+
We are using a tool called [poethepoet](https://github.com/nat-n/poethepoet) for task management and [uv](https://github.com/astral-sh/uv) for dependency management. At the [end of this document](#available-poe-tasks), you will find the available Poe tasks.
10+
911
## If you're on WSL
1012

1113
Check that you've cloned the repository to `~/workspace` or a similar folder.
@@ -461,3 +463,163 @@ or:
461463
This is assuming the upstream branch refers to the main repository. If you have a different name for the upstream branch, you can replace `upstream` with the name of your upstream branch.
462464

463465
After running the rebase command, you may need to resolve any conflicts that arise. If you are unsure how to resolve a conflict, please refer to the [GitHub's documentation on resolving conflicts](https://docs.github.com/en/get-started/using-git/resolving-merge-conflicts-after-a-git-rebase), or for [VSCode](https://code.visualstudio.com/docs/sourcecontrol/overview#_merge-conflicts).
466+
467+
# Task automation
468+
469+
## Available Poe Tasks
470+
This project uses [poethepoet](https://github.com/nat-n/poethepoet) for task management and [uv](https://github.com/astral-sh/uv) for dependency management.
471+
472+
### Setup and Installation
473+
474+
Once uv is installed, and you do not yet have a virtual environment setup:
475+
476+
```bash
477+
uv venv
478+
```
479+
480+
and then you can run the following tasks:
481+
```bash
482+
uv sync --all-extras --dev
483+
```
484+
485+
After this initial setup, you can use the following tasks to manage your development environment, it is adviced to use the following setup command since that also installs the pre-commit hooks.
486+
487+
#### `setup`
488+
Set up the development environment with a virtual environment, install dependencies and pre-commit hooks:
489+
```bash
490+
uv run poe setup
491+
# or with specific Python version
492+
uv run poe setup --python 3.12
493+
```
494+
495+
#### `install`
496+
Install all dependencies including extras and dev dependencies, including updates:
497+
```bash
498+
uv run poe install
499+
```
500+
501+
#### `venv`
502+
Create a virtual environment with specified Python version or switch python version:
503+
```bash
504+
uv run poe venv
505+
# or with specific Python version
506+
uv run poe venv --python 3.12
507+
```
508+
509+
#### `pre-commit-install`
510+
Install pre-commit hooks:
511+
```bash
512+
uv run poe pre-commit-install
513+
```
514+
515+
### Code Quality and Formatting
516+
517+
Each of the following tasks are designed to run against both the main `agent-framework` package and the extension packages, ensuring consistent code quality across the project.
518+
519+
#### `fmt` (format)
520+
Format code using ruff:
521+
```bash
522+
uv run poe fmt
523+
```
524+
525+
#### `lint`
526+
Run linting checks and fix issues:
527+
```bash
528+
uv run poe lint
529+
```
530+
531+
#### `pyright`
532+
Run Pyright type checking:
533+
```bash
534+
uv run poe pyright
535+
```
536+
537+
#### `mypy`
538+
Run MyPy type checking:
539+
```bash
540+
uv run poe mypy
541+
```
542+
543+
### Testing
544+
545+
#### `test`
546+
Run unit tests with coverage:
547+
```bash
548+
uv run poe test
549+
```
550+
551+
### Documentation
552+
553+
#### `docs-clean`
554+
Remove the docs build directory:
555+
```bash
556+
uv run poe docs-clean
557+
```
558+
559+
#### `docs-build`
560+
Build the documentation:
561+
```bash
562+
uv run poe docs-build
563+
```
564+
565+
#### `docs-serve`
566+
Serve documentation locally with auto-reload:
567+
```bash
568+
uv run poe docs-serve
569+
```
570+
571+
#### `docs-check`
572+
Build documentation and fail on warnings:
573+
```bash
574+
uv run poe docs-check
575+
```
576+
577+
#### `docs-check-examples`
578+
Check documentation examples for code correctness:
579+
```bash
580+
uv run poe docs-check-examples
581+
```
582+
583+
### Code Validation
584+
585+
#### `markdown-code-lint`
586+
Lint markdown code blocks:
587+
```bash
588+
uv run poe markdown-code-lint
589+
```
590+
591+
#### `samples-code-check`
592+
Run type checking on samples:
593+
```bash
594+
uv run poe samples-code-check
595+
```
596+
597+
### Comprehensive Checks
598+
599+
#### `check`
600+
Run all quality checks (format, lint, pyright, mypy, test, markdown lint, samples check):
601+
```bash
602+
uv run poe check
603+
```
604+
605+
#### `pre-commit-check`
606+
Run pre-commit specific checks (all of the above, excluding `mypy`):
607+
```bash
608+
uv run poe pre-commit-check
609+
```
610+
611+
### Building
612+
613+
#### `build`
614+
Build the package:
615+
```bash
616+
uv run poe build
617+
```
618+
619+
## Pre-commit Hooks
620+
621+
You can also run all checks using pre-commit directly:
622+
623+
```bash
624+
uv run pre-commit run -a
625+
```

0 commit comments

Comments
 (0)