Work in progress: this documentation is still being written and reviewed. Check details against the source code.

Robot agent client

Use an Anthropic-compatible Hermes client and stdio MCP sessions for a serial tool-use conversation loop. Tool callbacks can dispatch local GUI tools; API requests are synchronous even though chat is async.

beambot.agent.robot_agent · Source

Clients and integrations · Guide · Symbol index

How it is used

The command-line client and GUI bridge use RobotAgent to connect model responses to configured MCP tools. The lifecycle is connect() → repeated chat() calls → disconnect(); clear_history() starts a new conversation without reopening the connections.

GUI integrations can supply local tool definitions, an async dispatcher, and a tool filter. chat() is async but makes synchronous model requests and executes tool calls serially; text callbacks receive the final response, not a stream.

Start here

Callable

Purpose

RobotAgent.connect

Read the explicit or discovered MCP config, enter the exit stack, connect each listed stdio server and finally register caller-supplied local tools. Remote server failures do not stop later servers.

RobotAgent.chat

Append a user message and repeatedly call the synchronous model API, store text/tool-use blocks, execute requested tools serially and append their results until stop_reason is end_turn. on_text receives the final concatenated text once; this is not streaming.

RobotAgent.disconnect

Close the AsyncExitStack that owns MCP sessions and stdio processes.

RobotAgent.clear_history

Replace conversation history with a new empty list, retaining prompt, tools and connections.

RobotAgent

Conversation client that owns model history, MCP sessions, and tool routing. Callers manage its connection lifecycle and may extend the available tools through constructor arguments; it is not a ROS action server.

RobotAgent.connect()

Read the explicit or discovered MCP config, enter the exit stack, connect each listed stdio server and finally register caller-supplied local tools. Remote server failures do not stop later servers.

Lifecycle · Source

async connect(self)

Returns: None after attempted connections and registration.

Errors: Raises FileNotFoundError if no config is found; JSON/file errors propagate. Per-server exceptions are logged and suppressed. Malformed extra tool definitions can raise.

Side effects: Starts MCP subprocess sessions, populates tools/routing mappings and logs totals. Repeated calls do not clear prior registrations; duplicate names overwrite routing while remaining in the tools list.

RobotAgent.chat()

Append a user message and repeatedly call the synchronous model API, store text/tool-use blocks, execute requested tools serially and append their results until stop_reason is end_turn. on_text receives the final concatenated text once; this is not streaming.

Method · Source

async chat(self, user_message: str, on_tool_call=None, on_text=None) -> str

Parameter

Meaning

user_message

User request text appended to persistent conversation history.

on_tool_call

Optional synchronous callback(tool_name, arguments, result_text) after each executed tool.

on_text

Optional synchronous callback receiving final text when end_turn is returned.

Returns: Final concatenated text string from the end_turn response.

Errors: Model/API and callback exceptions propagate; tool dispatch errors normally become result strings. There is no iteration cap, and a non-end_turn response without tool calls repeats the loop.

Side effects: Sends prompt/history/tool metadata to the configured model service, grows messages, may invoke robot tools and blocks the event loop during synchronous API calls.

RobotAgent.disconnect()

Close the AsyncExitStack that owns MCP sessions and stdio processes.

Lifecycle · Source

async disconnect(self)

Returns: None after asynchronous resource cleanup.

Errors: Context-manager cleanup exceptions propagate.

Side effects: Closes sessions and subprocess transport contexts. Does not clear tool/history mappings or explicitly close the Anthropic client.

RobotAgent.clear_history()

Replace conversation history with a new empty list, retaining prompt, tools and connections.

Method · Source

clear_history(self)

Returns: None.

Errors: No explicit failure handling.

Side effects: Discards this agent’s message-history reference.

RobotAgent.__init__()

Create the API client, load/prepend the operation prompt and initialize history, MCP exit stack and local-tool/filter settings.

Lifecycle · Source

__init__(
    self,
    model = None,
    mcp_config_path = None,
    system_prompt_prefix: str = '',
    extra_tools: Optional[list] = None,
    extra_dispatch: Optional[Callable[[str, dict], Awaitable[str]]] = None,
    tool_filter: Optional[Callable[[str, str], bool]] = None,
)

Parameter

Meaning

model

Optional model override; falsy values use the environment/default model.

mcp_config_path

Optional MCP JSON configuration filename; None triggers cwd-parent search during connect.

system_prompt_prefix

Optional text prepended to the shared prompt with a Markdown separator.

extra_tools

Optional Anthropic-format local tool definitions, shallow-copied into an internal list.

extra_dispatch

Optional async (tool_name, arguments) dispatcher returning tool-result text for local tools.

tool_filter

Optional (server_name, tool_name) predicate deciding which remote tools to register.

Errors: Authentication environment, prompt file and API client initialization errors propagate.

Side effects: Reads configuration environment and prompt file, allocates API client/exit stack; no MCP subprocesses are started until connect.

Internal callbacks and helpers

RobotAgent._connect_server()

Start a configured stdio MCP process, initialize a ClientSession, list tools and register those accepted by the optional filter in Anthropic tool format.

Internal helper · Source

async _connect_server(self, name, server_cfg)

Parameter

Meaning

name

Configuration server name used in logs and filter calls.

server_cfg

Mapping with required command and optional args/env passed to StdioServerParameters.

Returns: None.

Errors: Process/protocol/filter errors propagate to connect’s per-server handler.

Side effects: Starts a subprocess, retains process/session contexts in the exit stack and appends tool definitions/routing entries; duplicate names replace the routing mapping.

Referenced in source (1)

RobotAgent._call_tool()

Route a name to its local async dispatcher or MCP session; collect remote textual content joined by newlines, falling back to str(result) when no text exists.

Internal helper · Source

async _call_tool(self, name: str, arguments: dict) -> str

Parameter

Meaning

name

Registered tool name.

arguments

Tool argument mapping forwarded unchanged.

Returns: Tool-result text, or an Error-prefixed string for unknown tool, missing local dispatcher or caught dispatch failure.

Errors: Catches ordinary local/remote dispatch exceptions and converts them to text; does not interpret remote isError separately.

Side effects: Invokes a registered tool, potentially controlling robot hardware or local GUI state.

Referenced in source (1)

RobotAgent._find_mcp_config()

Search cwd and up to nine further ancestors for the first existing .mcp.json path, stopping at filesystem root.

Internal helper · Source

_find_mcp_config(self)

Returns: Filename string, or None if none is found. Existence is checked, not whether it is a regular file.

Errors: Path/cwd filesystem errors propagate.

Side effects: Reads cwd and checks ancestor filesystem entries.

Referenced in source (1)

Functions

Internal callbacks and helpers

_create_client()

Construct an Anthropic client at HERMES_ENDPOINT plus /anthropic using AIFAPIM_API_KEY; return the BEAMBOT_MODEL selection alongside it.

Internal helper · Source

_create_client()

Returns: (client, model_name), defaulting to the Hermes NSLS-II endpoint and claude-sonnet-4-6.

Errors: Missing API key raises KeyError; Anthropic import/client-construction errors propagate.

Side effects: Reads environment variables and initializes a network client; does not itself make a model request.

Referenced in source (1)