---
title: Writing agent state
icon: "lucide/ArrowRight"
description: Write to agent's state from your application.
---
{/* TODO: Swap these links for Microsoft Agent Framework links once Microsoft Agent Framework is officially added to the feature viewer */}
<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>

## What is this?

This guide shows you how to write to your agent's state from your application.

## When should I use this?

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.

## Implementation

<Steps>
  <Step>
    ### Run and connect your agent
    <RunAndConnect />
  </Step>
  <Step>
    ### Define the Agent State
    Decide which parts of agent state you want to reflect in the UI and allow updating from the UI.

    <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";
    }
    ```
  </Step>
  <Step>
    ### Call `agent.setState` from the `useAgent` hook
    `useAgent` returns an `agent` object with a `setState` method that you can use to update the agent state. Calling this
    will update the agent state and trigger a rerender of anything that depends on the agent state.

    ```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>
          {/* [!code highlight:1] */}
          <p>Language: {agent.state?.language}</p>
          <button onClick={toggleLanguage}>Toggle Language</button>
        </div>
      );
    }
    ```
  </Step>
  <Step>
    ### Give it a try!
    You can now use `agent.setState` to update the agent state and `agent.state` to read it. Try toggling the language button
    and talking to your agent. You'll see the language change to match the agent's state.

<video src="https://cdn.copilotkit.ai/docs/copilotkit/images/coagents/write-agent-state.mp4" className="rounded-lg shadow-xl" loop playsInline controls autoPlay muted />
<Callout>
  This video shows the result of `npx copilotkit@latest init` with the implementation section applied to it!
</Callout>
  </Step>
</Steps>

## Advanced Usage

### Re-run the agent with a hint about what's changed

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.

```tsx title="ui/app/page.tsx"
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 (
    // ...
  );
}
```

### Notes on state updates
Depending on your agent implementation, you may choose to surface progress via tool responses or messages rather than frequent state snapshots. See [Generative UI](/microsoft-agent-framework/generative-ui/tool-rendering) for recommended patterns.
