A tool for routing messages between A2A enabled AI agents and marshalling MCP tool servers.
AgentRouter.mp4
Breaking Changes since v0.0.8
callbackFunctionhas been removed fromrouter.connectinfavor of event emissions (see below).- Sub-agent calls now use their own unique
taskIds to prevent task overlap. - Router no longer takes a generic
ContextManagerand now requires the newEventBuswhich centralizes event emissions across contexts. respondOnFinalOnlyhas been removed infavor ofTaskOptionscallAgentsnow usessendMessageinstead ofstreamMessage.
- Dynamic Dispatch: Route messages between multiple AI agents
- Automatic Discovery: Automatically detects local A2A servers
- Tool Integration: MCP tool integration with concurrent execution
- Session Management: Persistent sessions with message history
- Task Handoff: Supports context chaining by using A2A
referenceTasks
npm install @artinet/routerUse the create-agent command:
npx @artinet/create-agent@latestSelect the orchestrator agent to jump right into agent routing.
import { LocalRouter } from "@artinet/router";
const router = new LocalRouter();
const result = await router.connect({
message: "Hello, World!",
});Create an agent and define its behavior:
import { LocalRouter } from "@artinet/router";
import { AgentBuilder, FileStore, getPayload } from "@artinet/sdk";
const router = new LocalRouter();
router.createAgent({
engine: AgentBuilder()
.text(({ content: userInput }) => {
return userInput;
})
.createAgentEngine(),
agentCard: {
name: "EchoAgent",
description: "Echos back every request exactly",
...
},
});
//The router will dynamically orchestrate the agents & tools
const result: string = await router.connect({
message: "Use the echo agent to reply to me",
agents: ["EchoAgent"], // Provide a list of allowed agents
taskId: "task123", // Pass a taskId to resume a saved agent session
});
await router.close();Subscribe to updates like the results of tool/agent calls:
router.on("update", (response: any[]) => {
console.log(response);
});import { LocalRouter } from "@artinet/router";
import { AgentBuilder, FileStore } from "@artinet/sdk";
// Create a router with tools
const router = await LocalRouter.createRouter({
mcpServers: {
stdioServers: [
{
command: "npx",
args: [
"-y",
"@modelcontextprotocol/server-filesystem",
"/path/to/allowed/files",
],
},
{
command: "uvx",
args: ["mcp-server-fetch"],
},
],
},
});
// Convert the router into an agent
const agent = router.toAgent(
// Provide instructions for the agent to follow
"You are a File Management agent. Save every request you recieve in a text file",
{ // The AgentCard describing the Agent and it's skills
name: "File Manager",
description: "An agent that can manage the file system",
...
},
{ // Add optional whitelists for tools & agents (defaults to all available tools/agents)
tools: ["secure-filesystem-server"],
agents: [...],
}
);
// Interact with the new agent as you normally would
const result = agent.sendMessage({
message: {
...
role: "user",
parts: [{ kind: "text", text: "Please save this message" }],
},
});
await router.close();Implement an ApiProvider function to plug in your own backend.
Consume a ConnectRequest from the router and return a ConnectResponse.
Each ConnectRequest will include:
- The available tools/agents that have been whitelisted for the request.
- The responses/results of previous agent/tool calls. (e.g.
AgentResponse,ToolResponse)
Ensure that you include an array of ToolRequests and/or AgentRequests in your ConnectResponse. This will trigger the router to invoke those tools/agents
// Plug-in your own API function by converting tool/agent Calls into a format that the router will understand
const response = await router.connect({
message: {
session: { messages: [{ role: "user", content: "Hello!" }] },
apiProvider: async (request: ConnectRequest) => {
// The tools/agents available for this request
const availableTools = request.options?.tools?.localServers;
const availableAgents = request.options?.agents?.localServers;
// The responses/results of previous tool/agent invocations
const toolResponses = request.options?.tools?.results;
const agentResponses = request.options?.agents?.responses;
... // Call your own API here
// Then return a response including requests to any tools and agents
const response: ConnectResponse = {
agentResponse: "Hello!", // A response from the LLM
timestamp: new Date().toISOString(),
options: {
tools: {
results: [],
requests: [
{
// Format a tool request
kind: "tool_request",
callToolRequest: {
method: "tools/call",
params: {
name: "say-hello",
},
},
id: "hello-tool",
},
],
},
agents: {
responses: [],
requests: [
{
// Format an agent request
kind: "agent_request",
uri: "HelloAgent",
directive: "Say Hello!",
},
],
},
},
};
return response;
},
},
tools: ["hello-tool"],
agents: ["HelloAgent"],
});*Currently only supports stdio MCP Servers.
connect(params, tools[], agents[], callback?)- Execute task with routingcreateAgent(params)- Create new agent instancecreateTool(server)- Create tool from MCP serverclose()- Close all connections
This library leverages api.artinet.io to route commands to local agents & tools.
The @modelcontextprotocol/sdk will be changed to a peer dependancy in a future release.
Apache-2.0 - see LICENSE