Skip to main content
Attach plain TypeScript functions as agent tools, register them by name like Python, or wrap them in a FunctionTool for full control.

Quick Start

1

Simple Usage

2

Named Registration

Coming from Python’s FunctionTool.run? In TypeScript the runtime entry point is the tool() factory — import { tool } from 'praisonai' then tool(myFn). FunctionTool is the underlying class and is not meant to be instantiated directly.

Which One Do I Pick?

Three ways to build a tool, from least to most control.

Level 1 — Pass a Plain Function

The easiest way — hand the Agent your function directly. The model returns named arguments; the agent maps them onto your function’s parameters, so order doesn’t matter.
  • Named arguments map to your declared parameter names — order-independent.
  • Return values are JSON-serialized before going back to the model. Objects and null are safe — no manual JSON.stringify.
Without a description, the tool advertises itself as Tool: <name> (e.g. Tool: getWeather). Give it a clear description when you want the model to pick the right tool reliably.

Level 2 — Register by Name

Register a tool once on the global registry, then look it up anywhere — the same register_tool / get_tool names Python uses.
The global register_tool skips a name that is already taken (Python parity) — it logs a debug message and returns instead of throwing. Pass { overwrite: true } to replace an existing tool. The class method ToolRegistry.register throws on a duplicate instead.
register_tool accepts anything Python accepts — a plain function, a FunctionTool, or a BaseTool-like object with run() / execute().
register_tool writes to the name-keyed registry (the analogue of praisonaiagents/tools/registry.py). If you previously imported register_tool / get_tool from 'praisonai' and passed them tool ids or built instances, you were using the factory registry by accident — see Factory Registry for the one-line migration.

Level 3 — Full Control with FunctionTool

Wrap a function in a FunctionTool when you want to validate it, call it directly, or attach approval and retry behaviour.
Prefer tool({...}) if you don’t need a class instance — it returns the same FunctionTool:

.run() and .validate()

run() still goes through the same approval and restart-safety gates as execute — unlike Python’s raw run(). TypeScript has no per-name approval registry, so a raw run() here would be a second ungated door onto the same tool.
FunctionTool is not callable as a function. The Agent checks typeof tool === 'function' before the object branch, so a callable FunctionTool would bypass its own approval gate. It is kept intentionally non-callable — call .run() or .execute().

Trust Levels

Mark where a tool came from when you register it. TOOL_TRUST_LEVELS is ['trusted', 'external'].
An invalid trustLevel throws immediately. Read it back with get_registry().getTrustLevel(name).

Dynamic Schema Overrides

Reshape a parameter’s schema at registration time — useful for injecting enums from runtime state.

Multi Agents

Share tools across multiple Agents by passing the same functions:

Best Practices

Without a description, the tool advertises as Tool: <name> — the model has less to go on. A one-line description makes tool selection reliable.
Call .validate() on a FunctionTool before registration — it throws ToolValidationError listing every problem, so you catch a missing name or bad schema early.
Set trustLevel: 'external' for user-supplied code and 'trusted' for in-repo tools, so you can audit where a registered tool came from.
Use register_tool / get_tool for “I already have my tool”. Reach for the factory registry only when you build instances from user config.

Tools

Tool system overview

Factory Registry

Build tool instances from config

Tool Errors

Distinguish missing from broken

MCP Tools

External tool protocols