swift-agent
Version:
A building block of agentic systems: an LLM that can retrieve information, use tools, and store user inputs.
140 lines (126 loc) • 3.97 kB
text/typescript
import { BaseChatModel } from "@langchain/core/language_models/chat_models";
import {
BaseMessage,
HumanMessage,
SystemMessage,
} from "@langchain/core/messages";
import { MultiServerMCPClient } from "@langchain/mcp-adapters";
import { createReactAgent } from "@langchain/langgraph/prebuilt";
import {
MCPClientConfigInterface,
SwiftAgentOptionsInterface,
ToolInterface,
} from "./interfaces";
class SwiftAgent {
private _model: BaseChatModel;
private _options?: SwiftAgentOptionsInterface;
private _mcpClient?: MultiServerMCPClient;
private _tools: Array<ToolInterface> | undefined;
private _agent: ReturnType<typeof createReactAgent> | undefined;
private _messages: Array<BaseMessage> = [];
private _isInitialized: boolean = false;
constructor(model: BaseChatModel, options?: SwiftAgentOptionsInterface) {
this._model = model;
this._options = options;
if (this._options?.mcp) {
this._options.mcp.throwOnLoadError =
this._options.mcp.throwOnLoadError || true;
this._options.mcp.prefixToolNameWithServerName =
this._options.mcp.prefixToolNameWithServerName || true;
this._options.mcp.additionalToolNamePrefix =
this._options.mcp.additionalToolNamePrefix || "mcp";
this._mcpClient = new MultiServerMCPClient(
this._options.mcp as MCPClientConfigInterface,
);
}
if (options?.messageHistory) {
this._messages = options.messageHistory;
}
if (options?.systemPrompt) {
if (this._messages.length === 0) {
this._messages.push(new SystemMessage(options.systemPrompt));
} else if (this._messages[0].getType() === "system") {
this._messages[0].content = options.systemPrompt;
} else {
this._messages.unshift(new SystemMessage(options.systemPrompt));
}
}
}
get model() {
return this._model;
}
get options() {
return this._options;
}
get tools() {
return this._tools;
}
async run(message: string): Promise<BaseMessage[] | undefined> {
if (!this._isInitialized) {
this._tools = await this._getTools();
this._agent = createReactAgent({
llm: this._model,
tools: this._tools,
});
this._isInitialized = true;
}
try {
this._messages.push(new HumanMessage(message));
if (this._agent) {
const response = await this._agent.invoke({ messages: this._messages });
return response.messages;
} else {
console.error("Agent not initialized.");
return undefined;
}
} catch (e) {
console.error("Error during agent execution:", e);
}
}
setModel(model: BaseChatModel): void {
this._model = model;
this._agent = createReactAgent({
llm: this._model,
tools: this._tools || [],
});
}
enableMcpServer(serverName: string): void {
this._setToolsEnabled(serverName, true);
}
disableMcpServer(serverName: string): void {
this._setToolsEnabled(serverName, false);
}
private async _getTools(): Promise<ToolInterface[]> {
const allTools: Array<ToolInterface> = [];
for (const serverName of Object.keys(
this._mcpClient?.config.mcpServers || {},
)) {
const tools = (await this._mcpClient?.getTools(
serverName,
)) as Array<ToolInterface>;
for (const tool of tools) {
tool.serverName = serverName;
tool.isEnabled = true;
}
allTools.push(...tools);
}
return allTools;
}
private _setToolsEnabled(
serverName: string,
isEnabled: boolean = true,
): void {
const tools = this._tools?.filter((tool) => tool.serverName === serverName);
if (!tools || tools.length === 0) {
return;
}
for (const tool of tools) {
tool.isEnabled = isEnabled;
}
this._agent = createReactAgent({
llm: this._model,
tools: this._tools?.filter((tool) => tool.isEnabled) || [],
});
}
}
export default SwiftAgent;