/router

A typscript library for routing messages between A2A enabled AI agents and marshalling MCP tool servers.

Primary LanguageTypeScriptApache License 2.0Apache-2.0

Website npm version npm downloads Apache License Known Vulnerabilities GitHub stars Discord

@artinet/router

A tool for routing messages between A2A enabled AI agents and marshalling MCP tool servers.

AgentRouter.mp4

Breaking Changes since v0.0.8

  • callbackFunction has been removed from router.connect infavor of event emissions (see below).
  • Sub-agent calls now use their own unique taskIds to prevent task overlap.
  • Router no longer takes a generic ContextManager and now requires the new EventBus which centralizes event emissions across contexts.
  • respondOnFinalOnly has been removed infavor of TaskOptions
  • callAgents now uses sendMessage instead of streamMessage.

Features

  • 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

Installation

npm install @artinet/router

Quick Start

Use the create-agent command:

npx @artinet/create-agent@latest

Select the orchestrator agent to jump right into agent routing.

Basic Usage

import { LocalRouter } from "@artinet/router";

const router = new LocalRouter();

const result = await router.connect({
  message: "Hello, World!",
});

Router with Agents

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);
});

Router as Agent

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();

Bring Your Own API

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.

Core Commands

  • connect(params, tools[], agents[], callback?) - Execute task with routing
  • createAgent(params) - Create new agent instance
  • createTool(server) - Create tool from MCP server
  • close() - Close all connections

About

This library leverages api.artinet.io to route commands to local agents & tools.

Deprecation Notice

The @modelcontextprotocol/sdk will be changed to a peer dependancy in a future release.

License

Apache-2.0 - see LICENSE