
Security News
CVE Volume Surges Past 48,000 in 2025 as WordPress Plugin Ecosystem Drives Growth
CVE disclosures hit a record 48,185 in 2025, driven largely by vulnerabilities in third-party WordPress plugins.
@automattic/agenttic-ui
Advanced tools
React UI components for AI agent chat interfaces. A pure UI layer designed to work seamlessly with @automattic/agenttic-client hooks or any agent communication system.
npm install @automattic/agenttic-ui
import { useAgentChat } from '@automattic/agenttic-client';
import { AgentUI } from '@automattic/agenttic-ui';
function ChatApplication() {
const {
messages,
isProcessing,
error,
onSubmit,
abortCurrentRequest,
suggestions,
clearSuggestions,
messageRenderer,
} = useAgentChat( {
agentId: 'big-sky',
sessionId: 'my-session',
} );
return (
<AgentUI
messages={ messages }
isProcessing={ isProcessing }
error={ error }
onSubmit={ onSubmit }
onStop={ abortCurrentRequest }
suggestions={ suggestions }
clearSuggestions={ clearSuggestions }
messageRenderer={ messageRenderer }
variant="floating"
placeholder="Ask me anything..."
/>
);
}
For complete control over layout and component ordering:
import { AgentUI } from '@automattic/agenttic-ui';
function CustomChatLayout() {
return (
<AgentUI.Container
messages={ messages }
isProcessing={ isProcessing }
error={ error }
onSubmit={ onSubmit }
onStop={ abortCurrentRequest }
variant="embedded"
>
<AgentUI.ConversationView>
<AgentUI.Header />
<AgentUI.Messages />
<AgentUI.Footer>
<AgentUI.Notice />
<AgentUI.Input />
</AgentUI.Footer>
<AgentUI.Suggestions />
</AgentUI.ConversationView>
</AgentUI.Container>
);
}
External control of input value and changes:
function ExternallyControlledChat() {
const [ inputValue, setInputValue ] = useState( '' );
return (
<AgentUI
messages={ messages }
isProcessing={ isProcessing }
onSubmit={ onSubmit }
inputValue={ inputValue }
onInputChange={ setInputValue }
variant="embedded"
/>
);
}
AgentUI - Convenience wrapper with default layout AgentUI.Container - Root container with state management and context AgentUI.ConversationView - Conversation layout wrapper AgentUI.Header - Chat header with close/expand buttons AgentUI.Messages - Message history display AgentUI.Footer - Footer wrapper for input and notice AgentUI.Input - Text input with auto-resize AgentUI.Notice - Error and notification display AgentUI.Suggestions - Quick action suggestions
interface AgentUIProps {
// Core chat data
messages: Message[];
isProcessing: boolean;
error?: string | null;
onSubmit: ( message: string ) => void;
onStop?: () => void;
// UI configuration
variant?: 'floating' | 'embedded';
placeholder?: string | string[];
triggerIcon?: React.ReactNode;
notice?: NoticeConfig;
emptyView?: React.ReactNode;
// Chat state management (floating variant)
floatingChatState?: ChatState;
onOpen?: () => void;
onExpand?: () => void;
onClose?: () => void;
// Suggestions
suggestions?: Suggestion[];
clearSuggestions?: () => void;
// Message rendering
messageRenderer?: ComponentType< { children: string } >;
// Controlled input (optional)
inputValue?: string;
onInputChange?: ( value: string ) => void;
// Styling
className?: string;
style?: React.CSSProperties;
}
Place suggestions anywhere in your layout:
<AgentUI.Container {...props}>
<AgentUI.ConversationView>
<AgentUI.Messages />
<AgentUI.Suggestions /> {/* Above input */}
<AgentUI.Footer>
<AgentUI.Input />
</AgentUI.Footer>
</AgentUI.ConversationView>
</AgentUI.Container>
// Or below input:
<AgentUI.Container {...props}>
<AgentUI.ConversationView>
<AgentUI.Messages />
<AgentUI.Footer>
<AgentUI.Input />
</AgentUI.Footer>
<AgentUI.Suggestions /> {/* Below input */}
</AgentUI.ConversationView>
</AgentUI.Container>
Use individual components for complete customization:
import {
Messages,
Message,
ChatInput,
Suggestions,
} from '@automattic/agenttic-ui';
function FullyCustomChat() {
return (
<div className="my-chat-container">
<Messages
messages={ messages }
messageRenderer={ messageRenderer }
/>
<ChatInput
value={ inputValue }
onChange={ setInputValue }
onSubmit={ onSubmit }
placeholder="Type a message..."
isProcessing={ isProcessing }
/>
<Suggestions
suggestions={ suggestions }
onSuggestionClick={ onSubmit }
onClear={ clearSuggestions }
/>
</div>
);
}
Stop button appears automatically during processing:
<AgentUI
isProcessing={ isProcessing }
onStop={ abortCurrentRequest }
// Submit button becomes stop button when processing
/>
Content items can have different types that determine how they're displayed:
type: 'text' - Normal text content (visible)type: 'image_url' - Image content (visible)type: 'component' - React component (visible)type: 'context' - Context information sent as text to the agent but hidden from UI// Example: Mixing visible and context content
const messages = [
{
id: '1',
role: 'user',
content: [ { type: 'text', text: 'Take me to the dashboard' } ],
timestamp: Date.now(),
archived: false,
showIcon: true,
},
{
id: '2',
role: 'user',
content: [
{
type: 'context', // Hidden from UI, sent to agent for context
text: 'Navigation completed. Dashboard loaded successfully.',
},
],
timestamp: Date.now(),
archived: false,
showIcon: true,
},
{
id: '3',
role: 'agent',
content: [
{ type: 'text', text: "I've taken you to the dashboard." },
],
timestamp: Date.now(),
archived: false,
showIcon: true,
},
];
<AgentUI messages={ messages } />;
// Only messages 1 and 3 will be visible (message 2 has only context content)
// Example: Message with both visible and context content
const mixedMessage = {
id: '4',
role: 'user',
content: [
{ type: 'text', text: 'Here are your analytics' },
{ type: 'context', text: 'page: /analytics, loaded: true' },
],
timestamp: Date.now(),
archived: false,
showIcon: true,
};
// The context content will be filtered out, only "Here are your analytics" is visible
import { ReactMarkdown } from 'react-markdown';
const customRenderer = ( { children }: { children: string } ) => (
<ReactMarkdown remarkPlugins={ [ remarkGfm ] }>{ children }</ReactMarkdown>
);
<AgentUI messageRenderer={ customRenderer } />;
For floating variant, control state externally:
const [ chatState, setChatState ] = useState< ChatState >( 'collapsed' );
<AgentUI
variant="floating"
floatingChatState={ chatState }
onOpen={ () => setChatState( 'compact' ) }
onExpand={ () => setChatState( 'expanded' ) }
onClose={ () => setChatState( 'collapsed' ) }
/>;
Manages floating chat state:
const {
state, // 'collapsed' | 'compact' | 'expanded'
setState,
isOpen, // boolean
open, // () => void
close, // () => void
toggle, // () => void
} = useChat( initialState );
Manages input state with auto-resize:
const { value, setValue, clear, textareaRef, handleKeyDown, adjustHeight } =
useInput( {
value: inputValue,
setValue: setInputValue,
onSubmit: handleSubmit,
isProcessing: false,
} );
interface Message {
id: string;
role: 'user' | 'agent';
content: Array< {
type: 'text' | 'image_url' | 'component' | 'context';
text?: string;
image_url?: string;
component?: React.ComponentType;
componentProps?: any;
} >;
timestamp: number;
archived: boolean;
showIcon: boolean;
icon?: string;
actions?: MessageAction[];
disabled?: boolean;
}
interface MessageAction {
id: string;
icon?: React.ReactNode;
label: string;
onClick: ( message: Message ) => void | Promise< void >;
tooltip?: string;
disabled?: boolean;
pressed?: boolean;
showLabel?: boolean;
}
interface Suggestion {
id: string;
label: string;
prompt: string;
}
interface NoticeConfig {
icon?: React.ReactNode | null | false;
message: string;
action?: {
label: string;
onClick: () => void;
};
dismissible?: boolean;
onDismiss?: () => void;
}
type ChatState = 'collapsed' | 'compact' | 'expanded';
import '@automattic/agenttic-ui/index.css';
All styles are scoped to .agenttic class to prevent conflicts.
Override CSS custom properties:
.agenttic {
--color-primary: #your-brand-color;
--color-background: #ffffff;
--color-foreground: #000000;
}
.agenttic [data-slot='chat-footer'] {
--color-background: oklch( 1 0 0 );
--color-primary: #your-brand-color;
}
Pre-built icon components:
import {
ThumbsUpIcon,
ThumbsDownIcon,
CopyIcon,
StopIcon,
ArrowUpIcon,
XIcon,
BigSkyIcon,
StylesIcon,
} from '@automattic/agenttic-ui';
# Build the package
pnpm build
# Run in development mode
pnpm dev
# Run tests
pnpm test
# Type checking
pnpm type-check
# Start Storybook
pnpm storybook
import { useAgentChat } from '@automattic/agenttic-client';
import { AgentUI } from '@automattic/agenttic-ui';
function App() {
const agentProps = useAgentChat( {
agentId: 'big-sky',
} );
return <AgentUI { ...agentProps } variant="floating" />;
}
The useAgentChat hook returns props that match the AgentUI interface.
FAQs
UI components for the Agenttic framework
The npm package @automattic/agenttic-ui receives a total of 1,932 weekly downloads. As such, @automattic/agenttic-ui popularity was classified as popular.
We found that @automattic/agenttic-ui demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 52 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
CVE disclosures hit a record 48,185 in 2025, driven largely by vulnerabilities in third-party WordPress plugins.

Security News
Socket CEO Feross Aboukhadijeh joins Insecure Agents to discuss CVE remediation and why supply chain attacks require a different security approach.

Security News
Tailwind Labs laid off 75% of its engineering team after revenue dropped 80%, as LLMs redirect traffic away from documentation where developers discover paid products.