IACT (Inline Action-Clicked Text) is a Markdown-based inline interaction protocol designed specifically for AI Agents and LLM chat interfaces.
In traditional chat interfaces, when AI provides options, it typically uses lists or button blocks, disrupting conversation flow. IACT extends Markdown link syntax to embed interactive action anchors directly into natural language sentences, achieving "reading is interacting".
- 🎯 Inline over Block - Action options are organic parts of natural language
- ⚡ Zero Friction - Click text to instantly trigger intent flow
- 🔄 Seamless Degradation - Displays as normal links in standard Markdown renderers
- 🔒 Security & Constraints - No script execution or hidden link jumping
- 🔧 Infinitely Extensible - Developers can freely define custom directives based on business scenarios
[Display Text](!directive)Send text as user input directly to AI:
I can [conduct a deep market research](!send) for you, or directly [generate an industry report draft](!send).Fill text into input box, waiting for user to supplement before sending:
You can [provide more details](!add), for example, tell me what [specific visual styles](!add) you need.The image below demonstrates the IACT protocol in action:
In this example, the AI naturally embeds multiple interactive text anchors in its response:
[generate a complete PPT outline](!send)- Uses the!senddirective. When clicked, this text is immediately sent as a new conversation input to the AI, without manual typing[adjust specific section content](!add)- Uses the!adddirective. When clicked, the text is filled into the input box, allowing the user to continue specifying which section to adjust
The advantages of this design:
- Fluency: Interactive options are fully integrated into natural language sentences without disrupting the reading experience
- Intuitiveness: Users can see at a glance what they can do, without understanding complex button layouts
- Efficiency: Clicking triggers actions immediately, reducing the "think → type → send" workflow
- Selfware - Practical application scenarios and implementation examples of IACT protocol
For detailed protocol specification, please refer to:
Implementing IACT in front-end renderers is straightforward:
function IACTLink({ href, children }) {
if (href.startsWith('!')) {
const directive = href.slice(1);
const payload = extractText(children);
const handleClick = (e) => {
e.preventDefault();
if (directive === 'send') {
chatInterface.sendMessage(payload);
} else if (directive === 'add') {
chatInterface.appendToInputBox(payload);
}
};
return (
<a href="#" className="iact-anchor" onClick={handleClick}>
{children}
</a>
);
}
return <a href={href}>{children}</a>;
}The IACT protocol is designed to be open and infinitely extensible. Developers can freely define any custom directives starting with ! based on their Agent's business scenarios and client capabilities.
Beyond the core !send and !add directives, you can define more directives that fit your business needs:
<!-- File operations -->
[Open config file](!open_file:config.json)
<!-- Code application -->
[Apply this code](!apply_code)
<!-- Workflow triggers -->
[Start deployment process](!trigger_workflow:deploy)
<!-- Media interactions -->
[Play demo video](!play_media:demo.mp4)In your client implementation, simply extend the directive handling logic:
function IACTLink({ href, children }) {
if (href.startsWith('!')) {
const [directive, ...params] = href.slice(1).split(':');
const payload = extractText(children);
const handleClick = (e) => {
e.preventDefault();
// Core directives
if (directive === 'send') {
chatInterface.sendMessage(payload);
} else if (directive === 'add') {
chatInterface.appendToInputBox(payload);
}
// Custom directives
else if (directive === 'open_file') {
fileSystem.openFile(params[0]);
} else if (directive === 'apply_code') {
codeEditor.applyCode(payload);
} else if (directive === 'trigger_workflow') {
workflowEngine.trigger(params[0]);
}
};
return (
<a href="#" className="iact-anchor" onClick={handleClick}>
{children}
</a>
);
}
return <a href={href}>{children}</a>;
}When extending custom directives, we recommend following these principles:
- Clear Semantics: Directive names should intuitively express their functionality
- Concise Parameters: Use
:to separate directives and parameters, keeping syntax simple - Security First: Avoid executing arbitrary code or accessing sensitive resources
- Backward Compatibility: Ensure custom directives don't conflict with core directives
Issues and Pull Requests are welcome!
This protocol is fully open-sourced under the MIT License.
