Custom Tools

Register narrow app-specific native iOS tools for local development operations that the packaged suites do not cover.

Custom tools let app code expose a focused local development operation through the same guarded remote-tool protocol as the packaged suites.

Register a Tool

import AnsightCore

struct CurrentUserTool: AnsightTool {
    let userId: String

    var descriptor: AnsightToolDescriptor {
        AnsightToolDescriptor(
            id: "app.current_user",
            name: "Current User",
            description: "Returns the current debug user id.",
            category: "app",
            policy: .read
        )
    }

    func availability(
        context: AnsightToolAvailabilityContext
    ) -> AnsightToolAvailability {
        guard !userId.isEmpty else {
            return .unavailable(
                reasonCode: "user_not_signed_in",
                reason: "No debug user is signed in.",
                requiredState: "Signed-in debug session",
                remediation: "Open the account fixture and sign in.",
                retryable: true
            )
        }
        return .availableNow
    }

    func execute(arguments: [String: String]) throws -> AnsightToolExecutionResult {
        .success(.object([
            "userId": .string(userId)
        ]))
    }
}

try AnsightRuntime.shared.registerTool(
    CurrentUserTool(userId: session.currentUserId)
)

Descriptor-only registration is also available through registerTool(_ tool: AnsightToolDescriptor, replaceExisting:), but executable app tools should provide a concrete AnsightTool.

availability(context:) is optional because the protocol supplies .availableNow by default. Implement it when execution depends on current UI, account, database, or device state. The tool catalog publishes the result under runtime, sets executable, and re-evaluates availability immediately before execution.

Registration API

  • registerTool(_ tool: any AnsightTool, replaceExisting: Bool = false): registers an executable native tool.
  • registerTool(_ tool: AnsightToolDescriptor, replaceExisting: Bool = false): registers a descriptor-backed tool.
  • isToolRegistered(...): checks whether a tool id is currently registered.

Specific Concerns

  • Prefer narrow, app-specific operations.
  • Choose the correct policy: .read, .write, or .critical.
  • Do not expose broad scripting, arbitrary file access, or secret access through custom tools.
  • Registered tools are still hidden and unusable until the runtime guard allows their policy.

Tool Definition Checklist

  • Stable tool id, usually under an app-owned prefix such as app.
  • Clear name and description
  • Category and keywords that match the workflow
  • Correct policy
  • Arguments and result schemas when callers need structured inputs or outputs
  • Explicit failure messages for invalid arguments or unavailable app state
  • Stable availability reason codes, required state, remediation, and retryability when the tool has runtime prerequisites