This guide helps you migrate from AgentArea UI SDK v1.x to v2.0, which introduces significant new features and breaking changes.
- AgentUI Entry Point: Unified component with runtime management
- Artifact Display: Rich rendering for code, data, files, images, and text
- Input Collection: Dynamic forms, approvals, selections, and file uploads
- Communication Blocks: Protocol messages, status updates, and metadata
- Multi-Runtime Support: A2A protocol and AgentArea custom protocol
- Enhanced Error Handling: Component-level error boundaries
- SSR Support: Next.js and server-side rendering compatibility
- Component API changes and new prop requirements
- Provider structure modifications
- Hook signature updates
- Type definition changes
- Import path modifications
- Split into
@agentarea/coreand@agentarea/reactpackages - New component organization and export structure
- Enhanced TypeScript definitions
npm install @agentarea/ui-sdknpm install @agentarea/core @agentarea/react{
"dependencies": {
// Remove v1.x package
// "@agentarea/ui-sdk": "^1.0.0",
// Add v2.0 packages
"@agentarea/core": "^2.0.0",
"@agentarea/react": "^2.0.0"
}
}import {
AgentProvider,
TaskPrimitive,
AgentPrimitive,
useAgent,
useTask
} from '@agentarea/ui-sdk'// Core runtime and types
import {
createA2ARuntime,
createAgentAreaRuntime
} from '@agentarea/core'
// React components and hooks
import {
AgentUI,
AgentProvider,
TaskPrimitive,
AgentPrimitive,
Task,
Chat,
Artifact,
Input,
Block,
useAgent,
useTask,
useArtifacts,
useAgentConnection
} from '@agentarea/react'import { createA2ARuntime } from '@agentarea/ui-sdk'
const runtime = createA2ARuntime({
agentBaseUrl: 'http://localhost:9999'
})
<AgentProvider runtime={runtime}>
<TaskPrimitive.Root />
<AgentPrimitive.Root />
</AgentProvider>Option 1: Use New AgentUI Entry Point (Recommended)
import { AgentUI } from '@agentarea/react'
<AgentUI
runtime="a2a"
endpoint="http://localhost:9999"
autoConnect
debug
>
<Task.Root />
<AgentPrimitive.Root />
</AgentUI>Option 2: Continue with AgentProvider
import { createA2ARuntime } from '@agentarea/core'
import { AgentProvider } from '@agentarea/react'
const runtime = createA2ARuntime({
agentBaseUrl: 'http://localhost:9999'
})
<AgentProvider runtime={runtime}>
<Task.Root />
<AgentPrimitive.Root />
</AgentProvider>Option 3: Use Compound Component Pattern
<AgentUI.Provider runtime="a2a" endpoint="http://localhost:9999">
<AgentUI.Connection showStatus showActions />
<Task.Root />
<AgentUI.Debug showEnvironment />
</AgentUI.Provider><TaskPrimitive.Root>
<TaskPrimitive.Input
value={input}
onChange={setInput}
onSubmit={handleSubmit}
/>
<TaskPrimitive.Status />
<TaskPrimitive.Output />
</TaskPrimitive.Root>// Enhanced Task components with new capabilities
<Task.Root taskId="task-123">
<Task.Status />
<Task.Progress />
{/* NEW: Input request handling */}
<Task.InputRequest
requests={inputRequests}
onResponse={handleInputResponse}
/>
{/* NEW: Artifact display */}
<Task.Artifacts
artifacts={artifacts}
onDownload={handleDownload}
/>
{/* Enhanced chat interface */}
<Task.Chat />
</Task.Root>
// Or use the original primitive pattern (still supported)
<TaskPrimitive.Root>
<TaskPrimitive.Input
value={input}
onChange={setInput}
onSubmit={handleSubmit}
/>
<TaskPrimitive.Status />
<TaskPrimitive.Output />
</TaskPrimitive.Root>// Chat was basic in v1.x
<div className="chat-container">
<div className="messages">
{messages.map(msg => <div key={msg.id}>{msg.content}</div>)}
</div>
<input
value={input}
onChange={(e) => setInput(e.target.value)}
onKeyPress={handleKeyPress}
/>
</div>// Enhanced Chat components
<Chat.Root taskId="task-123">
{messages.map(message => (
<Chat.Message
key={message.id}
message={message}
showTimestamp
showSender
/>
))}
{/* NEW: Structured input forms */}
<Chat.InputForm
schema={{
fields: [
{ name: 'response', type: 'textarea', label: 'Your Response' },
{ name: 'priority', type: 'select', options: priorityOptions }
]
}}
onSubmit={handleFormSubmit}
/>
{/* Traditional text input still available */}
<Chat.Input
value={input}
onChange={setInput}
onSubmit={handleSubmit}
/>
</Chat.Root>const { task, isLoading, error, submitTask } = useTask('task-123')// Enhanced with new capabilities
const {
task,
isLoading,
error,
// NEW: Input request handling
inputRequests,
respondToInput,
// NEW: Artifact management
artifacts,
downloadArtifact,
// NEW: Communication blocks
communicationBlocks,
// Existing functionality
submitTask,
cancelTask,
subscribe
} = useTask('task-123')
// Handle input requests
if (inputRequests.length > 0) {
await respondToInput(inputRequests[0].id, { value: 'approved' })
}
// Download artifacts
const blob = await downloadArtifact('artifact-123')// NEW: Artifact management
const {
artifacts,
downloadArtifact,
uploadArtifact,
downloadProgress
} = useArtifacts('task-123')
// NEW: Agent connection management
const {
connection,
status,
connect,
disconnect
} = useAgentConnection('agent-123')
// NEW: Protocol message handling
const {
messages,
sendMessage,
markAsRead
} = useProtocolMessages()
// NEW: Runtime environment detection
const environment = useRuntimeEnvironment()
if (environment.isNextJS) {
// Next.js specific logic
}interface Task {
id: string
status: 'pending' | 'working' | 'completed' | 'failed'
input: string
output?: string
}
interface Agent {
id: string
name: string
description: string
capabilities: string[]
}// Enhanced task with new capabilities
interface EnhancedTask extends Task {
inputRequests?: TaskInputRequest[]
inputResponses?: InputResponse[]
communicationBlocks?: CommunicationBlock[]
enhancedArtifacts?: EnhancedArtifact[]
}
// New artifact types
interface EnhancedArtifact extends Artifact {
displayType: 'text' | 'code' | 'file' | 'image' | 'data'
renderOptions?: ArtifactRenderOptions
downloadable?: boolean
shareable?: boolean
}
// New input request types
interface TaskInputRequest {
id: string
type: 'text' | 'selection' | 'approval' | 'file' | 'form'
prompt: string
required: boolean
validation?: ValidationRule[]
options?: InputOption[]
metadata?: Record<string, unknown>
}import { createA2ARuntime } from '@agentarea/ui-sdk'
const runtime = createA2ARuntime({
agentBaseUrl: 'http://localhost:9999',
authentication: {
type: 'bearer',
token: 'your-token'
}
})import { createA2ARuntime, createAgentAreaRuntime } from '@agentarea/core'
// A2A Runtime
const a2aRuntime = createA2ARuntime({
agentBaseUrl: 'http://localhost:9999',
authentication: {
type: 'bearer',
token: 'your-token'
}
})
// NEW: AgentArea Custom Runtime
const agentAreaRuntime = createAgentAreaRuntime({
endpoint: 'wss://agentarea.example.com',
authentication: {
type: 'bearer',
token: 'your-token'
},
features: {
batchProcessing: true,
analytics: true,
templates: true
}
})
// NEW: Runtime switching
<AgentUI runtime={selectedRuntime}>
{/* Components adapt to runtime capabilities */}
</AgentUI>// Basic try-catch around components
try {
return (
<AgentProvider runtime={runtime}>
<TaskPrimitive.Root />
</AgentProvider>
)
} catch (error) {
return <div>Error: {error.message}</div>
}// Built-in error boundaries
<AgentUI runtime="a2a" endpoint="http://localhost:9999">
{/* Automatic error boundaries around component groups */}
<Task.Root taskId="task-123" />
<Chat.Root taskId="task-123" />
<Artifact artifact={artifact} />
</AgentUI>
// Custom error boundaries for specific needs
<TaskErrorBoundary fallback={<TaskErrorFallback />}>
<Task.Root taskId="task-123" />
</TaskErrorBoundary>
<ArtifactErrorBoundary fallback={<ArtifactErrorFallback />}>
<Artifact artifact={artifact} />
</ArtifactErrorBoundary>// Client-side only
function MyPage() {
return (
<AgentProvider runtime={runtime}>
<TaskPrimitive.Root />
</AgentProvider>
)
}// Next.js App Router
'use client'
import dynamic from 'next/dynamic'
import { Suspense } from 'react'
// Dynamic import for client-only features
const AgentUIWithRealTime = dynamic(
() => import('@agentarea/react').then(mod => mod.AgentUI),
{
ssr: false,
loading: () => <div>Loading agent interface...</div>
}
)
export default function AgentsPage() {
return (
<Suspense fallback={<PageSkeleton />}>
<AgentUIWithRealTime
runtime="a2a"
endpoint={process.env.NEXT_PUBLIC_AGENT_ENDPOINT}
autoConnect
>
<Task.List />
<Chat.Root />
</AgentUIWithRealTime>
</Suspense>
)
}/* Custom CSS for components */
.agent-card {
border: 1px solid #ccc;
padding: 1rem;
border-radius: 8px;
}
.task-status {
color: #28a745;
font-weight: bold;
}// Built-in Tailwind CSS classes and shadcn/ui components
<AgentUI theme="dark" className="custom-theme">
{/* Components use consistent design system */}
<Task.Root className="custom-task-styling">
<Task.Status /> {/* Styled with shadcn/ui variants */}
</Task.Root>
</AgentUI>
// CSS custom properties for theming
:root {
--primary-color: #007bff;
--success-color: #28a745;
--warning-color: #ffc107;
--danger-color: #dc3545;
}# Remove old package
npm uninstall @agentarea/ui-sdk
# Install new packages
npm install @agentarea/core @agentarea/reactReplace all imports from @agentarea/ui-sdk with the new package structure:
// Before
import { AgentProvider, TaskPrimitive } from '@agentarea/ui-sdk'
// After
import { createA2ARuntime } from '@agentarea/core'
import { AgentUI, Task } from '@agentarea/react'Strategy A: Minimal Changes (Backward Compatible)
- Keep existing component structure
- Update imports and runtime creation
- Gradually adopt new features
Strategy B: Full Migration (Recommended)
- Adopt AgentUI entry point
- Use new component families
- Implement enhanced error handling
- Add SSR support if using Next.js
Minimal Migration:
// Keep existing structure, just update imports
import { AgentProvider, TaskPrimitive } from '@agentarea/react'
import { createA2ARuntime } from '@agentarea/core'
const runtime = createA2ARuntime({ /* config */ })
<AgentProvider runtime={runtime}>
<TaskPrimitive.Root>
<TaskPrimitive.Input />
<TaskPrimitive.Status />
</TaskPrimitive.Root>
</AgentProvider>Full Migration:
// Adopt new AgentUI entry point and enhanced components
import { AgentUI, Task, Artifact, Input } from '@agentarea/react'
<AgentUI runtime="a2a" endpoint="http://localhost:9999" autoConnect>
<Task.Root taskId="task-123">
<Task.Status />
<Task.InputRequest onResponse={handleInput} />
<Task.Artifacts onDownload={handleDownload} />
</Task.Root>
</AgentUI>// Enhanced hook with new capabilities
const {
task,
inputRequests,
artifacts,
respondToInput,
downloadArtifact
} = useTask('task-123')
// Handle new features
useEffect(() => {
if (inputRequests.length > 0) {
// Handle input requests
}
}, [inputRequests])// Wrap components in error boundaries
<TaskErrorBoundary>
<Task.Root taskId="task-123" />
</TaskErrorBoundary>
<ArtifactErrorBoundary>
<Artifact artifact={artifact} />
</ArtifactErrorBoundary>- Test all existing functionality
- Verify new features work as expected
- Check error handling and edge cases
- Validate SSR if using Next.js
- Test performance and bundle size
Problem: Module not found: Can't resolve '@agentarea/ui-sdk'
Solution:
# Remove old package
npm uninstall @agentarea/ui-sdk
# Install new packages
npm install @agentarea/core @agentarea/react
# Update all imports
# From: import { ... } from '@agentarea/ui-sdk'
# To: import { ... } from '@agentarea/react'Problem: createA2ARuntime is not a function
Solution:
// Import from correct package
import { createA2ARuntime } from '@agentarea/core' // Not @agentarea/reactProblem: Property 'xyz' does not exist on type
Solution: Check the API Reference for updated prop interfaces:
// v1.x
<TaskPrimitive.Input value={input} onChange={setInput} />
// v2.0 - props may have changed
<Task.Input
value={input}
onChange={setInput}
onSubmit={handleSubmit} // New required prop
/>Problem: Type definitions don't match
Solution: Update TypeScript types and ensure you're using the correct interfaces:
// Import types from correct packages
import type { EnhancedTask, TaskInputRequest } from '@agentarea/core'Problem: Hydration errors in Next.js
Solution: Use SSR-safe patterns:
import { useIsClient } from '@agentarea/react'
function MyComponent() {
const isClient = useIsClient()
if (!isClient) {
return <div>Loading...</div>
}
return <AgentUI>{/* client-only content */}</AgentUI>
}// Update test imports
import { render, screen } from '@testing-library/react'
import { AgentUI, Task } from '@agentarea/react'
test('task renders correctly', () => {
render(
<AgentUI runtime="a2a" endpoint="http://localhost:9999">
<Task.Root taskId="test-task" />
</AgentUI>
)
expect(screen.getByText('Task Status')).toBeInTheDocument()
})// Test new features
test('input requests work correctly', async () => {
const handleResponse = jest.fn()
render(
<AgentUI runtime="a2a" endpoint="http://localhost:9999">
<Task.InputRequest
requests={mockInputRequests}
onResponse={handleResponse}
/>
</AgentUI>
)
// Test input request handling
fireEvent.click(screen.getByText('Approve'))
expect(handleResponse).toHaveBeenCalledWith('request-1', { approved: true })
})v2.0 introduces new components but maintains tree-shaking:
// Only import what you need
import { AgentUI, Task } from '@agentarea/react'
// Don't import: import * as AgentArea from '@agentarea/react'
// Use dynamic imports for heavy components
const Artifact = lazy(() => import('@agentarea/react').then(mod => ({ default: mod.Artifact })))- New error boundaries may add slight overhead
- Enhanced components include more features but are optimized
- Real-time features use efficient WebSocket connections
- Artifact rendering is lazy-loaded by default
- API Reference - Complete API documentation
- Examples - Working examples for all frameworks
- Troubleshooting Guide - Common issues and solutions
- Best Practices - Recommended patterns and practices
- GitHub Issues: Report bugs and request features
- Discussions: Ask questions and share experiences
- Discord: Real-time community support
If you need help with migration:
- Review this guide thoroughly
- Check the examples for your framework
- Test incrementally with small changes
- Use TypeScript for better error detection
- Reach out to the community for specific issues
AgentArea UI SDK v2.0 brings significant enhancements while maintaining backward compatibility where possible. The migration process is designed to be incremental, allowing you to adopt new features at your own pace.
Key benefits of migrating:
- ✅ Enhanced component capabilities
- ✅ Better error handling and resilience
- ✅ SSR and Next.js support
- ✅ Multi-runtime protocol support
- ✅ Improved TypeScript definitions
- ✅ Better performance and bundle optimization
Take your time with the migration, test thoroughly, and don't hesitate to reach out for help when needed.