Skip to content
Merged
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
3 changes: 3 additions & 0 deletions python/packages/azure-cosmos-memory/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ from agent_framework_azure_cosmos_memory import CosmosMemoryContextProvider

- Requires the `azure-cosmos-agent-memory` toolkit and an AI Foundry endpoint (used for both
embeddings and fact extraction).
- Documentation and examples that show a literal Foundry project endpoint must use the full project-scoped form
`https://your-account.services.ai.azure.com/api/projects/your-project`, including the `/api/projects/your-project`
path.
- Set a stable `user_id` in `state["user_id"]` or `session.state["user_id"]` for long-term,
cross-session memory. Without it, memory scopes to the ephemeral session id and the provider
logs a one-time warning.
Expand Down
3 changes: 3 additions & 0 deletions python/packages/core/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,9 @@ The vector store API is experimental under the shared `VECTOR_STORES` feature ID
- **`FoundryChatClient`** - Chat client for Microsoft Foundry project endpoints
- **`FoundryAgentSessionStore`** - Experimental Foundry-hosting session store, lazily re-exported from
`agent-framework-foundry-hosting`; currently backed by `azure.ai.agentserver.core.storage.FoundryStateStore`
- Documentation and examples that show a literal Foundry project endpoint must use the full project-scoped form
`https://your-account.services.ai.azure.com/api/projects/your-project`, including the `/api/projects/your-project`
path.

## Key Patterns

Expand Down
47 changes: 13 additions & 34 deletions python/samples/01-get-started/01_hello_agent.py
Original file line number Diff line number Diff line change
@@ -1,50 +1,29 @@
# Copyright (c) Microsoft. All rights reserved.

"""Create and run a minimal Agent Framework agent.

The agent uses a Microsoft Foundry chat client and prints one response.
For streaming, see `foundry_chat_client_basic.py` in:
https://github.com/microsoft/agent-framework/tree/main/python/samples/02-agents/providers/foundry
"""

import asyncio

from agent_framework import Agent
from agent_framework.foundry import FoundryChatClient
from azure.identity import AzureCliCredential

"""
Hello Agent — Simplest possible agent

This sample creates a minimal agent using FoundryChatClient via an
Microsoft Foundry project endpoint, and runs it in both non-streaming and streaming modes.

There are XML tags in all of the get started samples, those are used to display the same code in the docs repo.
"""


async def main() -> None:
# <create_agent>
client = FoundryChatClient(
project_endpoint="https://your-account.services.ai.azure.com/api/projects/your-project",
model="gpt-4o",
credential=AzureCliCredential(),
)

agent = Agent(
client=client,
name="HelloAgent",
client=FoundryChatClient(
Comment thread
eavanvalkenburg marked this conversation as resolved.
project_endpoint="https://your-account.services.ai.azure.com/api/projects/your-project",
model="gpt-6-luna",
Comment thread
eavanvalkenburg marked this conversation as resolved.
credential=AzureCliCredential(),
),
instructions="You are a friendly assistant. Keep your answers brief.",
)
# </create_agent>

# <run_agent>
# Non-streaming: get the complete response at once
result = await agent.run("What is the capital of France?")
print(f"Agent: {result}")
# </run_agent>

# <run_agent_streaming>
# Streaming: receive tokens as they are generated
print("Agent (streaming): ", end="", flush=True)
async for chunk in agent.run("Tell me a one-sentence fun fact.", stream=True):
if chunk.text:
print(chunk.text, end="", flush=True)
print()
# </run_agent_streaming>
Comment thread
eavanvalkenburg marked this conversation as resolved.
print(await agent.run("What is the largest city of France?"))
Comment thread
eavanvalkenburg marked this conversation as resolved.


if __name__ == "__main__":
Expand Down
58 changes: 16 additions & 42 deletions python/samples/01-get-started/02_add_tools.py
Original file line number Diff line number Diff line change
@@ -1,62 +1,36 @@
# Copyright (c) Microsoft. All rights reserved.

"""Give an agent a function tool.

The weather function is registered with @tool and passed to the agent.
Safety guidance: https://learn.microsoft.com/agent-framework/concepts/agents/safety
"""

import asyncio
from random import randint
from typing import Annotated

from agent_framework import Agent, tool
from agent_framework.foundry import FoundryChatClient
from azure.identity import AzureCliCredential
from pydantic import Field

"""
Add Tools — Give your agent a function tool

This sample shows how to define a function tool with the @tool decorator
and wire it into an agent so the model can call it.
"""


# <define_tool>
# NOTE: approval_mode="never_require" is for sample brevity.
# Use "always_require" in production for user confirmation before tool execution.
# For tools processing untrusted external data or performing privileged operations,
# review the Agent Safety guidance at
# https://learn.microsoft.com/en-us/agent-framework/concepts/agents/safety
Comment thread
eavanvalkenburg marked this conversation as resolved.
# and see samples/02-agents/security/email_security_example.py for SecureAgentConfig
# and quarantined_llm defense patterns.
# This read-only sample tool can run without approval.
@tool(approval_mode="never_require")
def get_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
def get_weather(location: str) -> str:
"""Get the weather for a given location."""
conditions = ["sunny", "cloudy", "rainy", "stormy"]
return f"The weather in {location} is {conditions[randint(0, 3)]} with a high of {randint(10, 30)}°C."


# </define_tool>
return f"The weather in {location} is sunny."


async def main() -> None:
client = FoundryChatClient(
project_endpoint="https://your-account.services.ai.azure.com/api/projects/your-project",
model="gpt-4o",
credential=AzureCliCredential(),
)

# <create_agent_with_tools>
agent = Agent(
client=client,
name="WeatherAgent",
instructions="You are a helpful weather agent. Use the get_weather tool to answer questions.",
client=FoundryChatClient(
project_endpoint="https://your-account.services.ai.azure.com/api/projects/your-project",
model="gpt-6-luna",
credential=AzureCliCredential(),
),
instructions="Use the weather tool to answer questions.",
tools=[get_weather],
)
# </create_agent_with_tools>

# <run_agent>
result = await agent.run("What's the weather like in Seattle?")
print(f"Agent: {result}")
# </run_agent>
print(await agent.run("What's the weather like in Seattle?"))


if __name__ == "__main__":
Expand Down
40 changes: 12 additions & 28 deletions python/samples/01-get-started/03_multi_turn.py
Original file line number Diff line number Diff line change
@@ -1,46 +1,30 @@
# Copyright (c) Microsoft. All rights reserved.

"""Reuse one agent session across multiple turns.

The shared session preserves conversation history between calls.
"""

import asyncio

from agent_framework import Agent
from agent_framework.foundry import FoundryChatClient
from azure.identity import AzureCliCredential

"""
Multi-Turn Conversations — Use AgentSession to maintain context

This sample shows how to keep conversation history across multiple calls
by reusing the same session object.
"""


async def main() -> None:
# <create_agent>
client = FoundryChatClient(
project_endpoint="https://your-account.services.ai.azure.com/api/projects/your-project",
model="gpt-4o",
credential=AzureCliCredential(),
)

agent = Agent(
client=client,
name="ConversationAgent",
client=FoundryChatClient(
project_endpoint="https://your-account.services.ai.azure.com/api/projects/your-project",
model="gpt-6-luna",
credential=AzureCliCredential(),
),
instructions="You are a friendly assistant. Keep your answers brief.",
)
# </create_agent>

# <multi_turn>
# Create a session to maintain conversation history
session = agent.create_session()

# First turn
result = await agent.run("My name is Alice and I love hiking.", session=session)
print(f"Agent: {result}\n")

# Second turn — the agent should remember the user's name and hobby
result = await agent.run("What do you remember about me?", session=session)
print(f"Agent: {result}")
# </multi_turn>
print(await agent.run("My name is Alice and I love hiking.", session=session))
print(await agent.run("What do you remember about me?", session=session))


if __name__ == "__main__":
Expand Down
88 changes: 26 additions & 62 deletions python/samples/01-get-started/04_memory.py
Original file line number Diff line number Diff line change
@@ -1,29 +1,21 @@
# Copyright (c) Microsoft. All rights reserved.

"""Persist a user's name with a context provider.

The provider stores the name in session state and injects it into later calls.
"""

import asyncio
from typing import Any

from agent_framework import Agent, AgentSession, ContextProvider, SessionContext
from agent_framework.foundry import FoundryChatClient
from azure.identity import AzureCliCredential

"""
Agent Memory with Context Providers and Session State

Context providers inject dynamic context into each agent call. This sample
shows a provider that stores the user's name in session state and personalizes
responses — the name persists across turns via the session.
"""


# <context_provider>
class UserMemoryProvider(ContextProvider):
"""A context provider that remembers user info in session state."""

DEFAULT_SOURCE_ID = "user_memory"

def __init__(self):
super().__init__(self.DEFAULT_SOURCE_ID)
def __init__(self) -> None:
super().__init__("user_memory")

async def before_run(
self,
Expand All @@ -33,18 +25,11 @@ async def before_run(
context: SessionContext,
state: dict[str, Any],
) -> None:
"""Inject personalization instructions based on stored user info."""
user_name = state.get("user_name")
if user_name:
context.extend_instructions(
self.source_id,
f"The user's name is {user_name}. Always address them by name.",
)
else:
context.extend_instructions(
self.source_id,
"You don't know the user's name yet. Ask for it politely.",
)
instructions = (
f"The user's name is {user_name}. Address them by name." if user_name else "Ask for the user's name."
)
context.extend_instructions(self.source_id, instructions)

async def after_run(
self,
Expand All @@ -54,51 +39,30 @@ async def after_run(
context: SessionContext,
state: dict[str, Any],
) -> None:
"""Extract and store user info in session state after each call."""
for msg in context.input_messages:
text = msg.text if hasattr(msg, "text") else ""
if isinstance(text, str) and "my name is" in text.lower():
state["user_name"] = text.lower().split("my name is")[-1].strip().split()[0].capitalize()


# </context_provider>
for message in context.input_messages:
text = message.text
if not isinstance(text, str):
continue
_, marker, name = text.lower().partition("my name is")
if marker and name.strip():
state["user_name"] = name.split()[0].capitalize()


async def main() -> None:
# <create_agent>
client = FoundryChatClient(
project_endpoint="https://your-account.services.ai.azure.com/api/projects/your-project",
model="gpt-4o",
credential=AzureCliCredential(),
)

agent = Agent(
client=client,
name="MemoryAgent",
client=FoundryChatClient(
project_endpoint="https://your-account.services.ai.azure.com/api/projects/your-project",
model="gpt-6-luna",
credential=AzureCliCredential(),
),
instructions="You are a friendly assistant.",
context_providers=[UserMemoryProvider()],
)
# </create_agent>

# <run_with_memory>
session = agent.create_session()

# The provider doesn't know the user yet — it will ask for a name
result = await agent.run("Hello! What's the square root of 9?", session=session)
Comment thread
eavanvalkenburg marked this conversation as resolved.
print(f"Agent: {result}\n")

# Now provide the name — the provider stores it in session state
result = await agent.run("My name is Alice", session=session)
print(f"Agent: {result}\n")

# Subsequent calls are personalized — name persists via session state
result = await agent.run("What is 2 + 2?", session=session)
print(f"Agent: {result}\n")

# Inspect session state to see what the provider stored
provider_state = session.state.get("user_memory", {})
print(f"[Session State] Stored user name: {provider_state.get('user_name')}")
# </run_with_memory>
print(await agent.run("Hello! What's the square root of 9?", session=session))
print(await agent.run("My name is Alice", session=session))
print(await agent.run("What is 2 + 2?", session=session))


if __name__ == "__main__":
Expand Down
33 changes: 33 additions & 0 deletions python/samples/01-get-started/05a_functional_workflow_basics.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Copyright (c) Microsoft. All rights reserved.

"""Compose two async functions into a functional workflow.

The workflow uppercases text, then reverses it using normal Python control flow.
"""

import asyncio

from agent_framework import workflow


async def to_upper_case(text: str) -> str:
return text.upper()


async def reverse_text(text: str) -> str:
return text[::-1]


@workflow
async def text_workflow(text: str) -> str:
upper = await to_upper_case(text)
return await reverse_text(upper)


async def main() -> None:
result = await text_workflow.build().run("hello world")
print(result.get_outputs()[0])


if __name__ == "__main__":
asyncio.run(main())
Loading
Loading