Skip to content

Semantic Probe

Introduction

Before calling a tool, the AI sometimes needs to know if the operation is possible, what the constraints are, or what options are available — without actually executing the side effect. Semantic Probes provide dry-run introspection for your tools.

What is a Semantic Probe?

A Semantic Probe is a read-only companion to a mutation or action. It answers: "Can I do this? What are the constraints?" without actually doing it.

typescript
const f = initFusion<AppContext>();

// The mutation (actual operation)
export const deleteProject = f.mutation('projects.delete')
  .describe('Permanently delete a project')
  .withString('id', 'Project ID')
  .handle(async (input, ctx) => {
    await ctx.db.projects.delete({ where: { id: input.id } });
    return { deleted: input.id };
  });

// The probe (dry-run check)
export const canDeleteProject = f.query('projects.can_delete')
  .describe('Check if a project can be deleted and list dependencies')
  .withString('id', 'Project ID')
  .handle(async (input, ctx) => {
    const project = await ctx.db.projects.findUnique({
      where: { id: input.id },
      include: { _count: { select: { tasks: true, members: true } } },
    });

    if (!project) return { canDelete: false, reason: 'Project not found' };

    const blockers = [];
    if (project._count.tasks > 0)
      blockers.push(`${project._count.tasks} active tasks`);
    if (project._count.members > 0)
      blockers.push(`${project._count.members} team members`);

    return {
      canDelete: blockers.length === 0,
      blockers,
      suggestion: blockers.length > 0
        ? 'Archive the project instead, or remove dependencies first.'
        : 'Safe to delete.',
    };
  });

The AI calls projects.can_delete first, sees the blockers, and either proceeds with the deletion or takes corrective action — without ever executing the destructive operation prematurely.

Usage

Probes are regular f.query() tools. The naming convention is {entity}.can_{action}:

ActionProbePurpose
projects.deleteprojects.can_deleteCheck dependencies
billing.chargebilling.can_chargeValidate payment method
users.promoteusers.can_promoteCheck role constraints

TIP

Probes naturally pair with Agentic Affordances. The probe's response can include suggest() hints that guide the AI to the actual action or to corrective steps.

Probe Composition

For complex workflows, compose probes to validate multiple steps before executing:

typescript
export const canPublishRelease = f.query('releases.can_publish')
  .describe('Check if a release is ready to publish')
  .withString('id', 'Release ID')
  .handle(async (input, ctx) => {
    const release = await ctx.db.releases.findUnique({
      where: { id: input.id },
      include: { tests: true, approvals: true },
    });

    const checks = [
      { name: 'All tests pass', ok: release.tests.every(t => t.status === 'pass') },
      { name: 'At least 2 approvals', ok: release.approvals.length >= 2 },
      { name: 'No blocking issues', ok: release.blockers === 0 },
      { name: 'Changelog written', ok: !!release.changelog },
    ];

    return {
      canPublish: checks.every(c => c.ok),
      checks,
      suggestion: checks.filter(c => !c.ok).map(c => c.name).join(', '),
    };
  });

The AI sees a checklist of requirements. If any check fails, it knows exactly what to fix before retrying the publish.