---
title: "State Rendering"
icon: "lucide/Bot"
description: Render the state of your agent with custom UI components.
---

{/* TODO: Re-add once the dojo example is updated and works */}
{/_ <IframeSwitcher
  id="agent-state-example"
  exampleUrl="https://feature-viewer.copilotkit.ai/adk-middleware/feature/agentic_generative_ui?sidebar=false&chatDefaultOpen=false"
  codeUrl="https://feature-viewer.copilotkit.ai/adk-middleware/feature/agentic_generative_ui?view=code&sidebar=false&codeLayout=tabs"
  exampleLabel="Demo"
  codeLabel="Code"
  height="700px"
/> _/}

## What is this?

All ADK Agents are stateful. This means that as your agent progresses through nodes, a state object is passed between them perserving
the overall state of a session. CopilotKit allows you to render this state in your application with custom UI components, which we call **Agentic Generative UI**.

## When should I use this?

Rendering the state of your agent in the UI is useful when you want to provide the user with feedback about the overall state of a session. A great example of this
is a situation where a user and an agent are working together to solve a problem. The agent can store a draft in its state which is then rendered in the UI.

## Implementation

<Steps>
  <Step>
    ### Run and connect your agent
    <RunAndConnect />
  </Step>
  <Step>
    ### Set up your agent with state

    Create your ADK agent with a stateful structure. Here's a complete example that tracks language selection:

    ```python title="agent.py"
    from typing import Dict
    from fastapi import FastAPI
    from pydantic import BaseModel
    from ag_ui_adk import ADKAgent, add_adk_fastapi_endpoint
    from google.adk.agents import LlmAgent
    from google.adk.tools import ToolContext


    class AgentState(BaseModel):
        """State for the agent."""
        language: str = "english"


    def set_language(tool_context: ToolContext, new_language: str) -> Dict[str, str]:
        """Sets the language preference for the user.

        Args:
            tool_context (ToolContext): The tool context for accessing state.
            new_language (str): The language to save in state.

        Returns:
            Dict[str, str]: A dictionary indicating success status and message.
        """
        tool_context.state["language"] = new_language
        return {"status": "success", "message": f"Language set to {new_language}"}


    agent = LlmAgent(
        name="my_agent",
        model="gemini-2.5-flash",
        instruction="You are a helpful assistant that can change language settings.",
        tools=[set_language],
    )

    adk_agent = ADKAgent(
        adk_agent=agent,
        app_name="demo_app",
        user_id="demo_user",
        session_timeout_seconds=3600,
        use_in_memory_services=True,
    )

    app = FastAPI()
    add_adk_fastapi_endpoint(app, adk_agent, path="/")

    if __name__ == "__main__":
        uvicorn.run(app, host="0.0.0.0", port=8000)
    ```

  </Step>
  <Step>
    ### Render state of the agent in the chat
    Now we can utilize `useAgent` with a `render` function to render the state of our agent **in the chat**.

    ```tsx title="app/page.tsx"
    // ...
    // ...

    // Define the state of the agent, should match the state of your ADK Agent.
    type AgentState = {
      language: string;
    };

    function YourMainContent() {
      // ...

      // [!code highlight:13]
      // styles omitted for brevity
      useAgent({
        agentId: "my_agent",
        render: ({ state }) => (
          <div>
            Current language: {state.language || 'not set'}
          </div>
        ),
      });

      // ...

      return <div>...</div>;
    }
    ```

    <Callout type="warn" title="Important">
      The `name` parameter must exactly match the agent name you defined in your CopilotRuntime configuration (e.g., `my_agent` from the quickstart).
    </Callout>

  </Step>
  <Step>
    ### Render state outside of the chat
    You can also render the state of your agent **outside of the chat**. This is useful when you want to render the state of your agent anywhere
    other than the chat.

    ```tsx title="app/page.tsx"
    // ...

    // Define the state of the agent, should match the state of your ADK Agent.
    type AgentState = {
      language: string;
    };

    function YourMainContent() {
      // ...

      // [!code highlight:3]
      const { agent } = useAgent({
        agentId: "my_agent",
      })

      // ...

      return (
        <div>
          {/* ... */}
          <div className="flex flex-col gap-2 mt-4">
            {/* [!code highlight:1] */}
            Current language: {agent.state?.language || 'not set'}
          </div>
        </div>
      )
    }
    ```

    <Callout type="warn" title="Important">
      The `name` parameter must exactly match the agent name you defined in your CopilotRuntime configuration (e.g., `my_agent` from the quickstart).
    </Callout>

  </Step>
  <Step>
    ### Give it a try!

    You've now created a component that will render the agent's state in the chat.

    <video
      src="https://cdn.copilotkit.ai/docs/copilotkit/images/coagents/agentic-generative-ui.mp4"
      className="rounded-lg shadow-xl"
      loop
      playsInline
      controls
      autoPlay
      muted
    />

  </Step>
</Steps>
