Skip to Content

Tool Registry

The Health AI Platform has two different tool concepts:

  1. A real Luna tool registry in apps/luna/src/lib/tools/index.ts
  2. A future shared workflow tool boundary implied by run_tool in @loop/workflow-engine

Understanding the difference matters when you write docs or add capabilities.

What exists today

The checked-in tool registry is the Luna registry:

import { lunaTools, toolCategories } from '@/lib/tools'; console.log(Object.keys(lunaTools)); console.log(toolCategories['Support & Community']);

It exports:

  • a map of tool names to tool implementations
  • category groupings for display and organization
  • a LunaToolName type derived from the registry keys

Registry shape

export const lunaTools = { 'product-search': productSearchTool, 'create-cart': createCartTool, 'lookup-orders': lookupOrdersTool, 'lookup-peptide': lookupPeptideTool, 'search-peptides': searchPeptidesTool, 'list-goals': listGoalsTool, 'list-stacks': listStacksTool, 'lookup-stack': lookupStackTool, 'safety-info': safetyInfoTool, 'update-customer-profile': updateCustomerProfileTool, 'save-note': saveNoteTool, 'suggest-resource': suggestResourceTool, 'suggest-action': suggestActionTool, 'create-support-ticket': createSupportTicketTool, 'get-community-insights': getCommunityInsightsTool, 'find-similar-users': findSimilarUsersTool, };

Tool categories

The Luna registry groups tools into categories:

CategoryExample tools
Product & Commerceproduct-search, create-cart, lookup-orders
Peptide Knowledgelookup-peptide, search-peptides, safety-info
Customer Managementupdate-customer-profile, save-note
UI/UXsuggest-resource, suggest-action
Support & Communitycreate-support-ticket, get-community-insights, find-similar-users

Example tool definition

The tools are defined with the AI SDK tool() helper and Zod parameters.

import { tool } from 'ai'; import { z } from 'zod'; export const productSearchTool = tool({ description: 'Search the product catalog by name, category, or use-case.', parameters: z.object({ category: z.enum(['supplements', 'treats', 'wellness', 'grooming', 'all']).optional(), productName: z.string().optional(), petType: z.enum(['dog', 'cat', 'horse', 'all']).optional(), healthGoal: z.string().optional(), }), execute: async ({ productName }) => { return { success: true, products: [], query: productName ?? null }; }, });

Runtime usage

An agent runtime can select from the registry by name:

import { lunaTools } from '@/lib/tools'; const toolName = 'lookup-peptide'; const tool = lunaTools[toolName];

That gives you:

  • a stable tool ID
  • validated parameter schemas
  • a single source of truth for available capabilities

Relationship to workflows

The workflow engine also exposes a run_tool step type:

- id: call-risk-tool type: run_tool action: type: tool params: toolId: risk-calculator

But today the workflow engine does not call the Luna registry directly.

Current behavior:

const result = await workflow.execute({ patientId: 'patient-42', tools: ['risk-calculator'], }); console.log(result.stepResults['call-risk-tool']);

The executor checks that the toolId is present in context.tools and then returns a stub execution result.

Why keep the boundary explicit

This separation is useful:

  • Luna can evolve its own tool set independently
  • workflows can still model tool eligibility
  • a future shared registry can preserve stable tool IDs without changing the DSL

Best practices

Use stable names

Prefer descriptive names like lookup-peptide or save-note.

const allowedTools = ['lookup-peptide', 'save-note'];

Validate parameters at the tool boundary

Use Zod schemas so the runtime and docs agree on expected arguments.

const parameters = z.object({ productName: z.string().optional(), healthGoal: z.string().optional(), });

Treat workflows and agent tools as separate layers

  • Workflows decide whether a capability should run
  • Tool registries decide how the capability executes

Current-state guidance

If you are documenting or building against the current repository:

  • Use the Luna registry as the concrete example of a working tool registry
  • Describe workflow run_tool as a controlled extension point
  • Avoid implying a shared @loop/tool-registry package already exists

Next steps