docs/content/docs/integrations/microsoft-agent-framework/shared-state/in-app-agent-write.mdx
import RunAndConnect from "@/snippets/integrations/microsoft-agent-framework/run-and-connect.mdx" import { IframeSwitcher } from "@/components/content" <IframeSwitcher id="shared-state-example" exampleUrl="https://feature-viewer.copilotkit.ai/microsoft-agent-framework-dotnet/feature/shared_state?sidebar=false&chatDefaultOpen=false" codeUrl="https://feature-viewer.copilotkit.ai/microsoft-agent-framework-dotnet/feature/shared_state?view=code&sidebar=false&codeLayout=tabs" exampleLabel="Demo" codeLabel="Code" height="700px" />
<Callout type="info"> This example demonstrates reading from shared state in the [CopilotKit Feature Viewer](https://feature-viewer.copilotkit.ai/microsoft-agent-framework-dotnet/feature/shared_state). </Callout>This guide shows you how to write to your agent's state from your application.
You can use this when you need to update agent state from your application — for example, changing user preferences, toggling settings, or providing user input that affects agent behavior.
<Tabs groupId="language_microsoft-agent-framework_agent" items={['.NET', 'Python']} persist>
<Tab value=".NET">
```csharp title="agent/Program.cs (excerpt)"
public class AgentStateSnapshot
{
public string Language { get; set; } = "english";
}
```
</Tab>
<Tab value="Python">
```python title="main.py"
from __future__ import annotations
import os
import uvicorn
from agent_framework import Agent, tool, SupportsChatGetResponse
from agent_framework.openai import OpenAIChatClient
from agent_framework.ag_ui import add_agent_framework_fastapi_endpoint
from agent_framework.ag_ui import AgentFrameworkAgent
from dotenv import load_dotenv
from fastapi import FastAPI
from typing import Annotated
from pydantic import BaseModel, Field
load_dotenv()
class SearchItem(BaseModel):
query: str
done: bool
STATE_SCHEMA: dict[str, object] = {
"language": {
"type": "string",
"enum": ["english", "spanish"],
"description": "Preferred language.",
}
}
PREDICT_STATE_CONFIG: dict[str, dict[str, str]] = {
"language": {"tool": "update_language", "tool_argument": "language"}
}
@tool
def update_language(
language: Annotated[str, Field(description="Preferred language: 'english' or 'spanish'")],
) -> str:
normalized = (language or "").strip().lower()
if normalized not in ("english", "spanish"):
return "Language unchanged. Use 'english' or 'spanish'."
return f"Language updated to {normalized}."
def _build_chat_client():
if os.getenv("AZURE_OPENAI_ENDPOINT"):
return OpenAIChatClient(
model=os.getenv("AZURE_OPENAI_CHAT_DEPLOYMENT_NAME", "gpt-4o-mini"),
api_key=os.getenv("AZURE_OPENAI_API_KEY"),
azure_endpoint=os.getenv("AZURE_OPENAI_ENDPOINT"),
)
if os.getenv("OPENAI_API_KEY"):
return OpenAIChatClient(
model=os.getenv("OPENAI_CHAT_MODEL_ID", "gpt-4o-mini"),
api_key=os.getenv("OPENAI_API_KEY"),
)
raise RuntimeError(
"Set either AZURE_OPENAI_ENDPOINT + AZURE_OPENAI_API_KEY, or OPENAI_API_KEY."
)
def create_agent(chat_client: SupportsChatGetResponse) -> AgentFrameworkAgent:
base_agent = Agent(
name="sample_agent",
instructions="You are a helpful assistant.",
client=chat_client,
tools=[update_language],
)
return AgentFrameworkAgent(
agent=base_agent,
name="CopilotKitMicrosoftAgentFrameworkAgent",
description="Assistant that tracks a simple language state.",
state_schema=STATE_SCHEMA,
predict_state_config=PREDICT_STATE_CONFIG,
require_confirmation=False,
)
chat_client = _build_chat_client()
agent = create_agent(chat_client)
app = FastAPI(title="Microsoft Agent Framework - Quickstart")
add_agent_framework_fastapi_endpoint(app=app, agent=agent, path="/")
if __name__ == "__main__":
uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)
```
</Tab>
</Tabs>
```ts title="ui/app/page.tsx"
type AgentState = {
language: "english" | "spanish";
}
```
```tsx title="ui/app/page.tsx"
import { useAgent } from "@copilotkit/react-core/v2"; // [!code highlight]
// Define the agent state type, should match the actual state of your agent
type AgentState = {
language: "english" | "spanish";
}
// Example usage in a pseudo React component
function YourMainContent() {
const { agent } = useAgent({ // [!code highlight]
agentId: "sample_agent",
initialState: { language: "english" } // optionally provide an initial state
});
// ...
const toggleLanguage = () => {
agent.setState({ language: agent.state?.language === "english" ? "spanish" : "english" }); // [!code highlight]
};
// ...
return (
// style excluded for brevity
<div>
<h1>Your main content</h1>
<p>Language: {agent.state?.language}</p>
<button onClick={toggleLanguage}>Toggle Language</button>
</div>
);
}
```
The new agent state will be used next time the agent runs.
If you want to re-run it manually, use copilotkit.runAgent().
The agent will be re-run with the latest updated state. You can also add a hint message before re-running.
import { useAgent, useCopilotKit } from "@copilotkit/react-core/v2";
// ...
function YourMainContent() {
const { agent } = useAgent({
agentId: "sample_agent",
});
const { copilotkit } = useCopilotKit(); // [!code highlight]
// setup to be called when some event in the app occurs
const toggleLanguage = async () => {
const newLanguage = agent.state?.language === "english" ? "spanish" : "english";
agent.setState({ language: newLanguage });
// add a hint message and re-run the agent
// [!code highlight:7]
agent.addMessage({
id: crypto.randomUUID(),
role: "user",
content: `the language has been updated to ${newLanguage}`,
});
await copilotkit.runAgent({ agent });
};
return (
// ...
);
}
Depending on your agent implementation, you may choose to surface progress via tool responses or messages rather than frequent state snapshots. See Generative UI for recommended patterns.