AgUiAgent
AgUiAgent is a stateless client implementation designed for cases where no ongoing context is needed or where the agent manages all state server-side. It provides a simple, efficient interface for interacting with AG-UI protocol agents.
Usage Scenarios
No Ongoing Context
Perfect for single interactions or independent queries:
val agent = AgUiAgent("https://api.example.com/agent") {
bearerToken = "your-token"
}
// Each interaction is independent
agent.sendMessage("What's the weather?").collect { state ->
println(state.messages.last().content)
}Agent-Managed State
Ideal when the agent handles conversation history server-side:
val agent = AgUiAgent("https://api.example.com/agent") {
bearerToken = "your-token"
// Agent manages conversation context internally
}
// Agent remembers previous interactions server-side
agent.sendMessage("My name is Bob").collect { }
agent.sendMessage("What's my name?").collect { state ->
// Agent retrieves context from server-side storage
}Configuration
Convenience Builders
The easiest way to create AgUiAgent instances:
// Quick bearer token setup
val agent = agentWithBearer("https://api.example.com/agent", "your-token")
// Quick API key setup
val agent = agentWithApiKey("https://api.example.com/agent", "your-api-key")
// Custom API key header
val agent = agentWithApiKey("https://api.example.com/agent", "your-key", "Authorization")
// Agent with tools
val agent = agentWithTools(
url = "https://api.example.com/agent",
toolRegistry = toolRegistry {
addTool(CalculatorToolExecutor())
}
) {
bearerToken = "your-token"
}
// Debug agent with logging
val agent = debugAgent("https://api.example.com/agent") {
bearerToken = "your-token"
}Basic Setup
val agent = AgUiAgent(
url = "https://api.example.com/agent"
) {
// Authentication (choose one)
bearerToken = "your-bearer-token"
// OR
apiKey = "your-api-key"
// OR
basicAuth("username", "password")
// Optional system prompt
systemPrompt = "You are a helpful assistant"
// Optional user ID
userId = "user-123"
}Advanced Configuration
val agent = AgUiAgent("https://api.example.com/agent") {
bearerToken = "your-token"
// Custom headers
customHeaders = mapOf(
"X-App-Version" to "1.0.0",
"X-Client-Type" to "mobile"
)
// Timeout settings
requestTimeout = 30.seconds
connectTimeout = 10.seconds
// Debug logging
enableLogging = true
// Custom user agent
userAgent = "MyApp/1.0"
}Methods
sendMessage
Send a message and receive streaming responses:
fun sendMessage(
message: String,
threadId: String = generateThreadId(),
state: JsonElement? = null,
includeSystemPrompt: Boolean = true
): Flow<BaseEvent>Parameters:
message: The message content to sendthreadId: Thread ID for conversation (defaults to generated ID)state: Initial state for the agent (defaults to null)includeSystemPrompt: Whether to include the configured system prompt
Returns: Flow<BaseEvent> - Stream of protocol events
Example:
agent.sendMessage("Calculate 15% tip on $50").collect { event ->
when (event) {
is TextMessageStartEvent -> println("Agent started responding")
is TextMessageContentEvent -> print(event.delta)
is TextMessageEndEvent -> println("\nAgent finished responding")
is ToolCallStartEvent -> println("Agent is using tool: ${event.toolCallName}")
is RunErrorEvent -> println("Error: ${event.message}")
}
}close
Close the agent and release resources:
fun close()Example:
class MyRepository {
private val agent = AgUiAgent("https://api.example.com/agent") {
bearerToken = "your-token"
}
fun cleanup() {
agent.close()
}
}
## Error Handling
### Connection Errors
```kotlin
agent.sendMessage("Hello").collect { state ->
state.errors.forEach { error ->
when (error.type) {
ErrorType.NETWORK -> {
println("Network error: ${error.message}")
// Handle network issues
}
ErrorType.AUTHENTICATION -> {
println("Auth error: ${error.message}")
// Handle authentication issues
}
ErrorType.PROTOCOL -> {
println("Protocol error: ${error.message}")
// Handle protocol violations
}
}
}
}Retry Logic
// Built-in retry for transient failures
val agent = AgUiAgent("https://api.example.com/agent") {
bearerToken = "your-token"
maxRetries = 3
retryDelay = 1.seconds
}Thread Safety
AgUiAgent is thread-safe and can be used concurrently:
val agent = AgUiAgent("https://api.example.com/agent") {
bearerToken = "your-token"
}
// Safe to call from multiple coroutines
launch {
agent.sendMessage("First message").collect { }
}
launch {
agent.sendMessage("Second message").collect { }
}Best Practices
Resource Management
// Agent automatically manages HTTP connections
// No explicit cleanup required, but you can control lifecycle:
class MyRepository {
private val agent = AgUiAgent(url) { /* config */ }
// Agent will be garbage collected when repository is
}Performance Optimization
// Reuse agent instances when possible
val agent = AgUiAgent(url) { bearerToken = token }
// Multiple interactions with same agent instance
repeat(10) { i ->
agent.sendMessage("Message $i").collect { }
}Message Threading
// Group related messages with threadId
val threadId = UUID.randomUUID().toString()
agent.sendMessage("Start conversation", threadId = threadId).collect { }
agent.sendMessage("Continue conversation", threadId = threadId).collect { }Platform Considerations
Android
- Uses Ktor Android engine (OkHttp under the hood)
- Handles network state changes automatically
- Compatible with background processing restrictions
iOS
- Uses Ktor Darwin engine (NSURLSession under the hood)
- Respects iOS app lifecycle events
- Compatible with background app refresh
JVM
- Uses Ktor CIO engine for server applications
- Supports high-concurrency scenarios
- Compatible with Spring Boot and other frameworks
