Skip to Content
Polyant is open source under AGPL-3.0 — star us on GitHub.

Tools

On this page

The Tools section (an agent’s Behaviour group) lists the tools enabled for this agent, lets you enable more from the engine’s catalogue, and is where you type the parameters (API keys and similar values) each tool asks for. Disabled tools are invisible to the assistant - the LLM does not see their schema, so it cannot call them.

Tool registration

Polyant ships with a built-in registry. Tools self-register at boot: each tool lives in its own *.tool.ts file under packages/engine/src/agents/tools/. Adding a tool is a one-file change; no central registry to update.

For the full schema of every tool (input/output shapes, required env vars, harness flag), see Tool catalog reference. For the architectural model behind tools (registry, dispatch, harness injection), see Tools concept.

Activity stream

When the activity-stream module is enabled, every tool invocation emits a live event on the SSE feed surfaced by the Activity screen (see Overview). The event carries the instance slug, tool name, input arguments (redacted for sensitive tools like slackPostMessage), and outcome. This is the recommended way to observe in-flight agent behavior without tailing engine logs.

spawnTask recursion guard

spawnTask is now guarded against infinite recursion: any transitive spawnTask call from inside a spawned task is rejected at dispatch time (the guard refuses all nested spawnTask calls, not just those past a depth threshold). This prevents runaway fan-out when an agent’s prompt accidentally recurses on its own delegation pattern. The previous behavior (silent fan-out until the LLM context ran out) is gone.

spawnTask is one of the three tools a new agent starts with, beside createSkill and readSkill. Before 1.2.0 it never reached the catalogue, so no agent could enable it: an existing agent that should delegate needs it enabled from this tab.

Categories

Tools are presented in groups. The grouping is informational - there is no functional difference between categories.

Channel I/O

  • send_outbound_message - sends a message to a connected channel from inside the agent loop. Used for proactive notifications and Room cycles.
  • slackPostMessage - posts a message to a Slack channel or DM via the instance’s Slack credentials. Resolves user IDs (U...) automatically by opening a DM. Works cross-channel: a conversation that came in on WhatsApp, web, or a webhook can still post to Slack - the inbound channel is irrelevant, only the outbound slack channel configuration on the instance matters. Optional slack_allowed_channels secret enforces an allowlist of destinations.
  • send_whatsapp_template - sends a pre-approved WhatsApp template message via Twilio.

Memory

  • saveMemory - explicitly persists a fact to long-term memory.
  • searchMemory - hybrid (vector + FTS) search over the memory store.

Knowledge base

  • searchKnowledge - search the per-instance knowledge files.
  • getKnowledge - fetch a single knowledge file by path.
  • writeKnowledge - create or update a knowledge file.

Web and HTTP

  • webSearch - multi-provider web search (Tavily / SerpAPI / DuckDuckGo, selectable via search_provider). The corresponding tavily_api_key / serpapi_api_key lives in instance secrets when the provider needs one.
  • httpRequest - generic HTTP request with SSRF protection and instance-scoped auth.
  • curl - escape-hatch tool that mirrors the curl CLI.

Files

  • readFile, writeFile, listDirectory - work inside the per-instance, per-conversation sandbox.

readFile returns at most 500 lines. To read further into a file, the model passes offset (the first line, counted from 1) and limit (at most 500), or tail for the last N lines of a log; the two forms cannot be combined. Every result carries the file’s total line count, so the model knows how much it has not seen. A file larger than 512 KB is refused.

Skills and automation

  • createSkill - create a skill in the organization’s catalogue and enable it on this agent.
  • readSkill - load a skill bundle into the conversation.
  • scheduleTask - schedule a future agent invocation (cron / interval / one-shot).
  • spawnTask - meta-tool that spawns an ad-hoc sub-agent for a single bounded task. Transitive spawnTask calls from inside a spawned task are rejected (no nested spawn at any depth).

Agent-to-agent

  • ask_<target_slug> - synthesized at runtime for every instance whose agent channel is enabled. The supervisor calls them like any other tool to delegate a sub-task to a peer agent. See concepts/channels.md for details.

Room control (harness tools)

  • send_message_to_human - send a message on the room’s outbound channel.
  • mark_events_completed - mark one or more events from the backlog as handled.
  • compact_room_history - explicitly compact the room’s conversation history.

These are harness tools (harness: true): injected only inside Room cycles (see Room tab) and never appear on the Tools tab toggle list.

Misc

  • updateSoul, updateUserProfile - runtime self-modifications to specific prompt sections.

MCP servers

The MCP section (also in Behaviour) lets an agent consume tools from an external Model Context Protocol server. Where the Tools section lists what the deployment ships, this one lists what the agent reaches out to.

Each server carries a slug (unique per agent), a display name, a URL, an auth mode, and an encrypted configuration blob. Reading them needs agent.channel:read; adding, editing, testing and deleting need agent.channel:write. A Test action dials the server and lists its tools before you save - the same idea, and the same permission, as testing a channel configuration.

Whatever the credential is, it is issued by the server you are connecting to, so its own documentation is the only place to get it. Nothing about it is a Polyant value - except in oauth mode, where the engine brokers the flow and the redirect URI to register with that server is <BASE_URL>/mcp/oauth/callback.

Three auth modes: none, static (a credential you supply), and oauth (the engine brokers the flow through /mcp/oauth/callback).

An imported server is not a trusted server

A remote server writes into the highest-trust part of the prompt, so it is treated as hostile input:

  • Tool names are namespaced and length-capped. Every remote tool is equipped as mcp__<server>__<tool>, so a remote tool can never collide with, or impersonate, a core or plugin tool.
  • Tool descriptions are sanitised, truncated, and wrapped in an untrusted_remote_description tag inside the system prompt. Without that, a third-party server would be writing directly into the stable cached prefix - the most trusted text the model sees.
  • The URL is checked when it is dialled, not only when it is saved. Loopback, private, link-local, unique-local and unspecified addresses are refused, in IPv4, IPv6, and IPv4-mapped-IPv6 forms - so 169.254.169.254 and [::ffff:169.254.169.254] are rejected by the same rule. That is an SSRF guard: without it, an admin-supplied URL would be a way to make the engine fetch its own cloud metadata endpoint.
  • A slow server cannot stall a turn. The connect-and-list round trip is bounded by the MCP connection (ms) installation policy (default 10 s), set at Admin Console → Installation policies with managed services and at Settings → General in the open-source build. On expiry the server is skipped for that turn exactly like a dead one.

A server that stops answering says so

Skipping a dead server for the turn kept the agent running but told nobody. The result of each connect is now persisted on the server row - when it was last checked, whether it worked, and the error if it did not.

Two things write it, and the second is the one that matters:

  • the Test action in this section, and
  • the runtime’s own per-turn connect. A server can pass a Test at nine in the morning and be unreachable all afternoon, and it is the afternoon the operator cares about.

The failure surfaces on the agent’s Status section as a broken check. Recording health never fails a turn: if the write itself errors, it is logged and the turn continues.

Adding and deleting a server are both recorded in the management audit.

Plugins are installed per organization

Beyond the built-in registry, a plugin contributes tools (and hooks, and OAuth providers) under its own namespace prefix. A deployment gets plugins in two ways: baked into the image, from PLUGIN_DIRS or the convention directory, and, with managed services, installed at runtime from a plugin marketplace.

The third-party integrations that used to ship inside the engine - the HubSpot CRM suite, the GitHub issue, pull-request and repository-cloning tools, the Render service tool, Markdown-to-PDF rendering and the S3 file upload - are plugins now, carried into a deployment only where they are wanted rather than registered in every installation. claudeCode and verifyDocument were removed with no replacement.

A plugin tool has a namespaced name:

Old toolNew toolPlugin
hubspotContact, hubspotDeal, hubspotTicket, hubspotNote, hubspotFile, hubspotSendEmail, hubspotCreateTask, hubspotMeeting, hubspotGetCompanyhubspot:contact, hubspot:deal, hubspot:ticket, hubspot:note, hubspot:file, hubspot:sendEmail, hubspot:createTask, hubspot:meeting, hubspot:getCompanypolyant-hubspot-plugin  v1.1.1
ghIssue, ghPR, gitCloneRepogithub:issue, github:pr, github:cloneRepono open-source plugin
renderServicerender:renderServiceno open-source plugin
markdownToPdfextra:markdownToPdfpolyant-extra-plugin  v1.1.0
fileUploadextra:fileUploadpolyant-extra-plugin  v1.1.0
claudeCode, verifyDocumentnone-

On the open-source build a plugin is added at build time: clone its release tag into packages/engine/src/plugins/<name> and rebuild the image, as each plugin’s README shows. For example:

git clone --depth 1 --branch v1.1.0 \ https://github.com/polyant-ai/polyant-extra-plugin.git \ packages/engine/src/plugins/extra

The GitHub and Render tools have no open-source plugin. With managed services, an organization can also install a plugin published on the marketplace without rebuilding the image.

The upgrade renames the old catalogue entries in place, so agents keep the tools they had enabled and skills keep their links, under the new names; governance policies that named the old tools are rewritten too. The tools come back as soon as the plugin reaches the agent, with nothing to re-enable. The upgrade guide has the details and the query for the two removed tools.

extra:fileUpload uploads a current message attachment or base64 data, up to 10 MB, to the agent’s own S3 bucket and returns its key and URL. It needs four agent secrets, s3_bucket_name, aws_region, aws_access_key_id and aws_secret_access_key, the same ones attachment storage uses, and reaches the bucket only with those static keys: when one is missing the tool sends nothing.

On the open-source engine a plugin baked into the image has its tools in every agent’s catalogue, and the rest of this section does not apply.

Managed services. The plugin marketplace and per-organization plugin policy are available with Polyant managed services.

What an organization installs

An Owner or Admin holding org.plugin:manage manages the organization’s plugins at Settings → Installed plugins (/organizations/{org}/settings/organization/plugins):

  • Add plugin browses the marketplace catalogue: the plugins available to this organization, with their tools, hooks, required secrets, OAuth providers, the knowledge access they need, and whether a hook may halt a turn or change a reply. A plugin from a marketplace other than the official one is labelled with its source, and one from an unsigned marketplace as Unverified.
  • Install picks a release. The latest compatible one is the default; an earlier one can be chosen instead.
  • An installed plugin’s sheet changes its version, for an update or a rollback, and uninstalls it. A version switch first runs a preflight, which refuses to drop a tool or hook an agent still uses and lists the affected agents. A deprecated release can only be the target of a rollback; a revoked or locally blocked release cannot be selected at all.
  • Uninstalling keeps every agent’s configuration, so a later install restores it.

Installing does not assign the plugin to any workspace or enable any tool: assign it in Workspaces → Plugins, then enable its tools on each agent. The organization’s overview page and the workspace home warn when an installed release or the catalogue is unavailable, name the agents affected, and list available updates.

The marketplace serves signed releases. The engine verifies the catalogue’s signature and each bundle’s digest and size before it extracts anything, runs a marketplace plugin’s code in a worker thread per organization and release, and downloads and verifies every selected release again at each boot. A release can declare no system packages: a plugin with a system block in its manifest needs packages installed in the image, so it is available only baked into the image.

org.plugin:read, which Admin and Owner hold too, reads the organization’s plugins, their health and the catalogue without changing anything. It is separate from org:read, the membership floor every role holds, which would otherwise let anyone inside the tenant enumerate what the installation runs. Member and Viewer hold neither.

What a platform admin decides

A platform admin manages the installation’s side at Admin Console → Plugins (/platform/settings/plugins). It is platform-admin-only, deliberately a role check rather than a permission: a grantable right to widen a tenant’s tool set would itself be a privilege-escalation surface.

  • Marketplaces. Every deployment reads the official marketplace, whose signing keys ship with the engine. A platform admin adds further marketplaces, each with one or more Ed25519 public keys it must be signed with. An unsigned marketplace needs an explicit acknowledgement and, in production, is read only when the deployment sets PLUGIN_MARKETPLACE_ALLOW_UNSIGNED=true: nobody vouches for its catalogue, and its code runs in the engine that serves every organization. A plugin belongs to the first marketplace that published it, the official one first, so an added marketplace can never take over an official plugin. A marketplace cannot be removed or switched off while an organization has one of its plugins installed.
  • Releases. The page shows the catalogue, every organization’s installed version and the health of each installation. Block release stops a release for every organization on this installation, permanently, and stops its running workers. Terminate worker stops one organization’s worker for a release; a later call can start it again.
  • Who may install what. A marketplace plugin is allowed in every organization unless a platform admin denies it there. Denying a plugin an organization has installed removes the installation and its workspace assignments and stops its worker at once, keeping agent configuration. Allowing it again lets the organization install it anew. Both are recorded in the management audit.
  • Image plugins. A plugin baked into the image reaches an organization only through a platform admin grant, under Image plugins. A plugin this engine cannot run cannot be granted; revoking is always allowed and keeps agent configuration for a later grant. When an image plugin first appears at boot, every organization that exists then is granted it once, so an upgrade keeps working; an organization created later needs an explicit grant.

The same allow and deny switches, and the image plugin grants, are also on one organization’s page at Admin Console → Organizations → the organization → Plugins.

Installed or granted makes a plugin assignable, not available

The organization half is only the first of two boundaries. A plugin’s tools reach an agent when the organization has it installed (or, for an image plugin, granted) and the agent’s workspace has it assigned, from Workspaces → Plugins. A workspace created after the allow-list shipped starts with nothing assigned, and installing or granting a plugin does not assign it anywhere.

Where the workspace half is the missing one, this tab says so: a banner counts the plugins the agent uses that its workspace does not carry, and their tools are simply not served.

A plugin the organization does not hold is invisible, not merely inert

The runtime has always refused the tools and hooks of a plugin the organization does not hold. They are also absent from the management plane: every catalog endpoint used to publish the names, descriptions and required-secret hints of every plugin the installation runs, which discloses what the installation runs and, by implication, who else runs it. A marketplace plugin denied to the organization is absent from its catalogue too.

Filtered: this tab’s tool list and its save, the required-secrets list, the global tool registry, the governance tool list, and the hook-function catalogue. Both resolvers fail closed.

Deliberately not filtered: an agent’s export bundle and the compliance configuration snapshot. Those report the tenant’s own persisted rows - filtering them would break the export/import round-trip and falsify an audit record of what was configured. An export records the plugin releases an agent depends on; importing it never installs a plugin, so install the same release in the destination organization first.

What a revoke does to this tab

Rows belonging to a plugin you cannot see are left untouched by a save. They are not deleted, and they do not make the tab unsavable - matching the rule that rows survive a revoke, a denial or an uninstall, so a later install or grant restores the configuration exactly.

Requesting to add the tool of a plugin the organization does not hold is refused with the same message as an unknown tool, so the refusal is not an existence oracle.

Enabling and disabling tools

The tab lists only the tools this agent has enabled, one row each, with Name, Description and Origin (Built-in, or the plugin’s display name). Search enabled tools… and the Origin and Category filters narrow the list. A tool the engine keeps on whatever this page says is listed last as Always enabled, with no actions.

To add tools, click Enable tools. The picker browses the catalogue by Categories or by Plugins, marks what is already enabled, and under each tool that needs a value says Will ask for: … with the parameters it will need. Pick one or more tools and confirm with Enable N. A plugin groups its tools in the picker but is never switched as a whole: each tool is enabled on its own.

Enabling and disabling are a draft until you click the page’s Save. A drafted row stays in the list and says To enable · save to confirm or To disable · save to confirm, and Restore undoes a drafted removal. Disabling a tool the agent has now asks for confirmation first. If an enabled skill needs that tool, the dialog says so, and the skill is disabled together with it when you save. The change applies to new conversations immediately; in-flight conversations finish with the previous tool set.

The tool panel

Click a row to open the tool’s panel. The description is held to three lines, with Show all for the rest (most of it is written for the model). Below it:

  • Parameters lists every value the tool declares, each with its label and description and an Asked for by … line naming the enabled tools that share the key. A key a plugin’s tools share is typed once. Values are saved with Save parameters in the panel footer, separately from the page’s Save, so you can fill them in before the tool itself is saved. Closing with unsaved values asks first. Only someone who can manage the agent’s credentials sees and changes the values; anyone else sees the labels only.
  • Other plugin tools, for a plugin tool, lists the plugin’s remaining tools, each with its own switch. These switches change the page’s draft like any other.
  • A warning when the tool would do nothing even while enabled: its plugin is not enabled for the organization, or memory or knowledge is off for this agent.

Disable in the footer works like disabling from the row, confirmation included.

When tools need credentials

Many tools need API keys or other values (Tavily, Slack, Twilio, a plugin’s own service). Type them in the tool’s panel, under Parameters. The values are agent secrets, encrypted at rest. For the keys an organization is allowed to share (s3_bucket_name, for example, but not aws_region), a value in the organization’s shared credentials also satisfies the tool; see Manage secrets. When you enable a tool that cannot run without a value, its panel opens straight on the missing fields.

A row whose required values are missing says Missing names. Open the tool to configure it. Until they are filled in, the tool is not served: the model does not see it on any turn, and nothing reports an error in the conversation. A tool that calls a model itself reads the agent’s provider keys from Model, and its panel links there; with managed services it receives the keys of the agent’s chat provider connection and nothing else.

Last updated on