@automattic/agenttic-client
A TypeScript client library for connecting to the Automattic agent framework with React hooks and component integration.
Original based on the A2A (Agent2Agent), but it has morphed to meet our internal needs so there is no longer a direct relationship to that protocol.
Installation
npm install @automattic/agenttic-client
Key Features
- React hooks for agent communication (
useAgentChat, useClientContext, useClientTools, useClientAbilities)
- Streaming and non-streaming responses
- Tool execution system with automatic handling
- Compatibility with WordPress Abilities API
- Context injection for each message
- Conversation persistence and management
- Request cancellation with abort controllers
- TypeScript support
- Message actions and markdown rendering
Quick Start
Basic Chat Integration
import { useAgentChat } from '@automattic/agenttic-client';
function ChatComponent() {
const {
messages,
isProcessing,
error,
onSubmit,
registerSuggestions,
registerMarkdownComponents
} = useAgentChat({
agentId: 'big-sky',
sessionId: 'my-session-123',
authProvider: async () => ({ Authorization: 'Bearer your-token' })
});
return (
<div>
{messages.map(msg => (
<div key={msg.id} className={msg.role}>
{msg.content.map(content => content.text).join('')}
</div>
))}
<input
onKeyDown={(e) => e.key === 'Enter' && onSubmit(e.target.value)}
disabled={isProcessing}
/>
{error && <div>Error: {error}</div>}
</div>
);
}
With Tools and Context
import { useAgentChat, useClientTools, useClientContext } from '@automattic/agenttic-client';
function AdvancedChatComponent() {
const contextProvider = useClientContext(() => ({
page: window.location.href,
timestamp: Date.now(),
userRole: getCurrentUserRole()
}));
const toolProvider = useClientTools(
async () => [
{
id: 'calculator',
name: 'Calculator',
description: 'Perform mathematical calculations',
input_schema: {
type: 'object',
properties: {
expression: { type: 'string' }
},
required: ['expression']
}
}
],
async (toolId, args) => {
if (toolId === 'calculator') {
return { result: calc(args.expression)};
}
}
);
const chat = useAgentChat({
agentId: 'big-sky',
contextProvider,
toolProvider,
authProvider: async () => ({ Authorization: 'Bearer token' })
});
return <ChatInterface {...chat} />;
}
With Abilities
WordPress Abilities API integration allows you to expose WordPress capabilities as tools to agents.
import { useAgentChat, useClientAbilities } from '@automattic/agenttic-client';
import { getAbilities, executeAbility } from '@wordpress/abilities';
function WordPressChat() {
const [abilities, setAbilities] = useState([]);
useEffect(() => {
getAbilities().then(setAbilities);
}, []);
const toolProvider = useClientAbilities(abilities, executeAbility);
const chat = useAgentChat({
agentId: 'wp-assistant',
toolProvider,
authProvider: async () => ({ Authorization: 'Bearer token' })
});
return <ChatInterface {...chat} />;
}
You can also combine regular tools with abilities using useClientToolsWithAbilities:
const toolProvider = useClientToolsWithAbilities( {
getClientTools: async () => myCustomTools,
executeTool: async ( toolId, args ) => {
},
abilities,
executeAbility,
} );
Core APIs
useAgentChat Hook
The primary hook for chat functionality, providing everything needed for a complete chat interface.
const {
messages,
isProcessing,
error,
onSubmit,
abortCurrentRequest,
registerSuggestions,
registerMarkdownComponents,
registerMessageActions,
messageRenderer,
addMessage,
} = useAgentChat( config );
Config Options:
agentId: string - Required. Agent identifier
agentUrl?: string - Agent endpoint URL (defaults to WordPress.com)
sessionId?: string - Session ID for conversation persistence
contextProvider?: ContextProvider - Dynamic context injection
toolProvider?: ToolProvider - Tool execution capabilities
authProvider?: AuthProvider - Authentication headers
useClientContext Hook
Provides dynamic context that refreshes with each message.
const contextProvider = useClientContext( () => ( {
currentPage: {
url: window.location.href,
title: document.title,
selectedText: getSelection(),
},
user: {
role: getUserRole(),
permissions: getPermissions(),
},
timestamp: Date.now(),
} ) );
useClientTools Hook
Enables agents to execute tools in your application.
const toolProvider = useClientTools(
async () => [
{
id: 'file-reader',
name: 'File Reader',
description: 'Read file contents',
input_schema: {
type: 'object',
properties: {
path: { type: 'string' },
},
required: [ 'path' ],
},
},
],
async ( toolId, args ) => {
if ( toolId === 'file-reader' ) {
return { content: await readFile( args.path ) };
}
throw new Error( `Unknown tool: ${ toolId }` );
}
);
useClientAbilities Hook
Converts WordPress Abilities to Agenttic tools automatically.
import { getAbilities, executeAbility } from '@wordpress/abilities';
const abilities = await getAbilities();
const toolProvider = useClientAbilities( abilities, executeAbility );
WordPress Abilities can be:
- Server-side: Executed via REST API (no
callback property)
- Client-side: Executed in browser (has
callback function)
The API handles both types automatically, routing execution appropriately.
useClientToolsWithAbilities Hook
Combines regular tools and WordPress Abilities in a single provider.
import { getAbilities, executeAbility } from '@wordpress/abilities';
const abilities = await getAbilities();
const toolProvider = useClientToolsWithAbilities( {
getClientTools: async () => [
{ id: 'calculator', name: 'Calculator' },
],
executeTool: async ( toolId, args ) => {
},
abilities,
executeAbility,
} );
createClient Function
Low-level client for direct communication without React.
import { createClient } from '@automattic/agenttic-client';
const client = createClient({
agentId: 'big-sky',
authProvider: async () => ({ Authorization: 'Bearer token' }),
toolProvider: {
getAvailableTools: async () => [...],
executeTool: async (toolId, args) => ({ result: '...' })
}
});
const task = await client.sendMessage({
message: createTextMessage('Hello'),
sessionId: 'session-123'
});
for await (const update of client.sendMessageStream({
message: createTextMessage('Hello'),
sessionId: 'session-123'
})) {
console.log(update.text);
if (update.final) break;
}
const abortController = new AbortController();
const task = await client.sendMessage({
message: createTextMessage('Hello'),
sessionId: 'session-123',
abortSignal: abortController.signal
});
abortController.abort();
Agent Manager
Functional singleton for managing multiple agent instances.
import { getAgentManager } from '@automattic/agenttic-client';
const manager = getAgentManager();
await manager.createAgent( 'my-agent', {
agentId: 'big-sky',
sessionId: 'session-123',
contextProvider,
toolProvider,
} );
const task = await manager.sendMessage( 'my-agent', 'Hello' );
for await ( const update of manager.sendMessageStream( 'my-agent', 'Hello' ) ) {
console.log( update );
}
const history = manager.getConversationHistory( 'my-agent' );
await manager.resetConversation( 'my-agent' );
Additional Features
Request Cancellation
Cancel in-flight requests using the built-in abort functionality:
const { abortCurrentRequest, isProcessing } = useAgentChat( config );
if ( isProcessing ) {
abortCurrentRequest();
}
For low-level client usage, use AbortController:
import {
createClient,
createAbortController,
} from '@automattic/agenttic-client';
const client = createClient( config );
const abortController = createAbortController();
const requestPromise = client.sendMessage( {
message: createTextMessage( 'Hello' ),
abortSignal: abortController.signal,
} );
abortController.abort();
try {
await requestPromise;
} catch ( error ) {
if ( error.name === 'AbortError' ) {
console.log( 'Request was cancelled' );
}
}
Message Actions
Add interactive buttons to agent messages:
const { registerMessageActions, createFeedbackActions } =
useAgentChat( config );
registerMessageActions(
createFeedbackActions( {
onFeedback: async ( messageId, feedback ) => {
console.log( `${ feedback } feedback for ${ messageId }` );
},
icons: { up: '👍', down: '👎' },
} )
);
registerMessageActions( {
id: 'copy-actions',
actions: [
{
id: 'copy',
label: 'Copy',
icon: '📋',
onClick: ( message ) =>
navigator.clipboard.writeText( message.content[ 0 ].text ),
},
],
} );
Markdown Extensions
Extend markdown rendering with custom components:
import { BarChart, LineChart } from '@automattic/agenttic-client';
const { registerMarkdownComponents, registerMarkdownExtensions } = useAgentChat(config);
registerMarkdownComponents( {
h1: ({ children }) => (
<h1 className="text-2xl font-bold text-brand">{children}</h1>
),
code: ({ children, className }) => (
<SyntaxHighlighter language={className}>
{children}
</SyntaxHighlighter>
),
a: ({ href, children }) => (
<a href={href} target="_blank" rel="noopener">
{children} ↗
</a>
),
blockquote: ( { children, ...props } ) => (
<blockquote
{ ...props }
style={ {
borderLeft: '4px solid #007cba',
backgroundColor: '#f0f8ff',
margin: '16px 0',
padding: '12px 16px',
fontStyle: 'italic',
borderRadius: '0 4px 4px 0',
} }
>
{ children }
</blockquote>
),
});
registerMarkdownExtensions({
charts: {
BarChart,
LineChart
}
});
Conversation Suggestions
Provide suggested prompts to users:
const { registerSuggestions, clearSuggestions } = useAgentChat( config );
registerSuggestions( [
{
id: '1',
label: 'Help me write code',
prompt: 'Can you help me write a function?',
},
{
id: '2',
label: 'Explain this error',
prompt: 'What does this error mean?',
},
] );
Type Definitions
interface UIMessage {
id: string;
role: 'user' | 'agent';
content: Array< {
type: 'text' | 'image_url' | 'component';
text?: string;
image_url?: string;
component?: React.ComponentType;
} >;
timestamp: number;
actions?: UIMessageAction[];
}
interface Tool {
id: string;
name: string;
description: string;
input_schema: {
type: 'object';
properties: Record< string, any >;
required?: string[];
};
}
type AuthProvider = () => Promise< Record< string, string > >;
type ContextProvider = { getClientContext: () => any };
type ToolProvider = {
getAvailableTools: () => Promise< Tool[] >;
executeTool: ( toolId: string, args: any ) => Promise< any >;
};
Development
pnpm build
pnpm test
pnpm type-check
pnpm lint