@automattic/agenttic-client
A TypeScript client library for Agent2Agent (A2A) protocol communication with React hooks and component integration. Built for seamless AI agent integration in both browser and Node.js environments.
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 A2A 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