Skip to content

Adding a New Tool (Level A)

This project uses Level A tools:

  • Tool handlers are implemented in code (safe, reviewable).
  • Tool availability is dynamic (protocol-driven + admin overrides) and is kept in sync between:
    • LangChain tool list (what the agent can call)
    • prompt injection (what the model is told is available)

The Source of Truth (what to edit)

1) Register the tool (catalog + UI metadata)

File: backend/src/config/toolCatalog.ts

  • Add the new tool id to the ToolId union.
  • Add a toolCatalog entry with label, description, category, mode, and access defaults.
  • Keep enabled: true if it’s allowed to run in production.
    Admins can still disable it at runtime via the enablement override system.

2) Add the input schema (shared by executor + LangChain)

File: backend/src/services/tools/toolSchemas.ts

  • Add a Zod schema for the tool input.
  • Add it to TOOL_SCHEMA_BY_ID[toolId].

This is critical: the schema is used for both tool execution validation and LangChain tool argument validation.


3) Implement the tool handler (execution)

File: backend/src/services/toolExecutor.service.ts

  • Add a new entry in the executors map:
    • schema: use the schema from toolSchemas.ts
    • requiresFile: set if it needs uploads
    • handler: implement the actual logic

Tool execution enforces:

  • Enablement override (admin can disable tools at runtime)
  • Access policy (allowedProtocols, targetScope) plus DB overrides

File: backend/src/services/tools/toolCompilation.service.ts

  • Add an entry to TOOL_PROMPT_META[toolId] with:
    • description
    • args (human-readable argument descriptions)
    • example (optional)

This improves the quality of tool use because the agent sees clearer tool docs inside prompts.


Make the tool available to a protocol

Tools are dynamically selected per turn by the compiler.

Update the protocol definition:

  • Field: protocol.toolConfig.allowedTools
  • Add your tool id to the array.

If a protocol does not specify allowedTools, the system falls back to a default conversational tool set.

Option B: keep default set

If your tool is meant to be universally available, add it to the default list:

  • File: backend/src/services/tools/toolCompilation.service.ts
  • Constant: DEFAULT_CONVERSATIONAL_TOOLS

Admin overrides (runtime controls)

Enable/disable tools without redeploy

Admin API:

  • GET /api/admin/tool-enablement
  • PUT /api/admin/tool-enablement/:toolId with { "enabled": true|false|null }
  • DELETE /api/admin/tool-enablement/:toolId (reset to code default)

Notes:

  • Level A safety: if a tool is enabled: false in code, admin overrides do not resurrect it.

Restrict tools by protocol / scope

Admin API:

  • GET /api/admin/tool-permissions
  • PUT /api/admin/tool-permissions/:toolId with { allowedProtocols, targetScope }
  • DELETE /api/admin/tool-permissions/:toolId (reset)

Checklist (copy/paste)

  • [ ] Add tool id + catalog entry in backend/src/config/toolCatalog.ts
  • [ ] Add Zod schema + TOOL_SCHEMA_BY_ID entry in backend/src/services/tools/toolSchemas.ts
  • [ ] Add executor handler in backend/src/services/toolExecutor.service.ts
  • [ ] Add prompt meta in backend/src/services/tools/toolCompilation.service.ts (recommended)
  • [ ] Add tool to protocol allowlist (protocol.toolConfig.allowedTools) or default set
  • [ ] Verify tool appears in prompt
  • [ ] Verify tool appears in LangChain tool list and runs successfully
  • [ ] (Optional) Add/adjust tool access + enablement via admin UI

ASO Universal Consciousness System Documentation