showcase/shell-docs/src/content/ag-ui/concepts/agents.mdx
Agents are the core components in the AG-UI protocol that process requests and generate responses. They establish a standardized way for front-end applications to communicate with AI services through a consistent interface, regardless of the underlying implementation.
In AG-UI, an agent is a class that:
Agents can be implemented to connect with any AI service, including:
All agents in AG-UI extend the AbstractAgent class, which provides the
foundation for:
class MyAgent extends AbstractAgent {
run(input: RunAgentInput): RunAgent {
// Implementation details
}
}
AG-UI agents have several key components:
AG-UI provides different agent implementations to suit various needs:
The base class that all agents extend. It handles core event processing, state management, and message history.
A concrete implementation that connects to remote AI services via HTTP:
const agent = new HttpAgent({
url: "https://your-agent-endpoint.com/agent",
headers: {
Authorization: "Bearer your-api-key",
},
});
You can create custom agents to integrate with any AI service by extending
AbstractAgent:
class CustomAgent extends AbstractAgent {
// Custom properties and methods
run(input: RunAgentInput): RunAgent {
// Implement the agent's logic
}
}
To create a custom agent, extend the AbstractAgent class and implement the
required run method:
AbstractAgent,
RunAgent,
RunAgentInput,
EventType,
BaseEvent,
} from "@ag-ui/client"
class SimpleAgent extends AbstractAgent {
run(input: RunAgentInput): RunAgent {
const { threadId, runId } = input
return () =>
new Observable<BaseEvent>((observer) => {
// Emit RUN_STARTED event
observer.next({
type: EventType.RUN_STARTED,
threadId,
runId,
})
// Send a message
const messageId = Date.now().toString()
// Message start
observer.next({
type: EventType.TEXT_MESSAGE_START,
messageId,
role: "assistant",
})
// Message content
observer.next({
type: EventType.TEXT_MESSAGE_CONTENT,
messageId,
delta: "Hello, world!",
})
// Message end
observer.next({
type: EventType.TEXT_MESSAGE_END,
messageId,
})
// Emit RUN_FINISHED event
observer.next({
type: EventType.RUN_FINISHED,
threadId,
runId,
})
// Complete the observable
observer.complete()
})
}
}
Agents in the AG-UI protocol provide a rich set of capabilities that enable sophisticated AI interactions:
Agents establish bi-directional communication channels with front-end applications through event streams. This enables:
Agents can use tools to perform actions and access external resources. Importantly, tools are defined and passed in from the front-end application to the agent, allowing for a flexible and extensible system:
// Tool definition
const confirmAction = {
name: "confirmAction",
description: "Ask the user to confirm a specific action before proceeding",
parameters: {
type: "object",
properties: {
action: {
type: "string",
description: "The action that needs user confirmation",
},
importance: {
type: "string",
enum: ["low", "medium", "high", "critical"],
description: "The importance level of the action",
},
details: {
type: "string",
description: "Additional details about the action",
},
},
required: ["action"],
},
};
// Running an agent with tools from the frontend
agent.runAgent({
tools: [confirmAction], // Frontend-defined tools passed to the agent
// other parameters
});
Tools are invoked through a sequence of events:
TOOL_CALL_START: Indicates the beginning of a tool callTOOL_CALL_ARGS: Streams the arguments for the tool callTOOL_CALL_END: Marks the completion of the tool callFront-end applications can then execute the tool and provide results back to the agent. This bidirectional flow enables sophisticated human-in-the-loop workflows where:
This mechanism is particularly powerful for implementing interfaces where AI and
humans collaborate. For example, CopilotKit
leverages this exact pattern with their
useCopilotAction hook,
which provides a simplified way to define and handle tools in React
applications.
By keeping the AI informed about human decisions through the tool mechanism, applications can maintain context and create more natural collaborative experiences between users and AI assistants.
Agents maintain a structured state that persists across interactions. This state can be:
STATE_DELTA eventsSTATE_SNAPSHOT events// Accessing agent state
console.log(agent.state.preferences);
// State is automatically updated during agent runs
agent.runAgent().subscribe((event) => {
if (event.type === EventType.STATE_DELTA) {
// State has been updated
console.log("New state:", agent.state);
}
});
AG-UI supports agent-to-agent handoff and collaboration:
For example, a general assistant agent might hand off to a specialized coding agent when programming help is needed, passing along the conversation context and specific requirements.
Agents support human intervention and assistance:
This enables applications where the agent acts as a collaborative partner rather than an autonomous system.
Agents maintain a complete history of conversation messages:
// Accessing message history
console.log(agent.messages);
// Adding a new user message
agent.messages.push({
id: "msg_123",
role: "user",
content: "Can you explain that in more detail?",
});
Agents can emit metadata about their internal processes:
This allows front-ends to provide transparency into the agent's decision-making process and help users understand how conclusions were reached.
Once you've implemented or instantiated an agent, you can use it like this:
// Create an agent instance
const agent = new HttpAgent({
url: "https://your-agent-endpoint.com/agent",
});
// Add initial messages if needed
agent.messages = [
{
id: "1",
role: "user",
content: "Hello, how can you help me today?",
},
];
// Run the agent
agent
.runAgent({
runId: "run_123",
tools: [], // Optional tools
context: [], // Optional context
})
.subscribe({
next: (event) => {
// Handle different event types
switch (event.type) {
case EventType.TEXT_MESSAGE_CONTENT:
console.log("Content:", event.delta);
break;
// Handle other events
}
},
error: (error) => console.error("Error:", error),
complete: () => console.log("Run complete"),
});
Agents accept configuration through the constructor:
interface AgentConfig {
agentId?: string; // Unique identifier for the agent
description?: string; // Human-readable description
threadId?: string; // Conversation thread identifier
initialMessages?: Message[]; // Initial messages
initialState?: State; // Initial state object
}
// Using the configuration
const agent = new HttpAgent({
agentId: "my-agent-123",
description: "A helpful assistant",
threadId: "thread-456",
initialMessages: [
{ id: "1", role: "system", content: "You are a helpful assistant." },
],
initialState: { preferredLanguage: "English" },
});
AG-UI agents maintain state across interactions:
// Access current state
console.log(agent.state);
// Access messages
console.log(agent.messages);
// Clone an agent with its state
const clonedAgent = agent.clone();
Agents are the foundation of the AG-UI protocol, providing a standardized way to
connect front-end applications with AI services. By implementing the
AbstractAgent class, you can create custom integrations with any AI service
while maintaining a consistent interface for your applications.
The event-driven architecture enables real-time, streaming interactions that are essential for modern AI applications, and the standardized protocol ensures compatibility across different implementations.