Skip to main content
You want every tool invocation — search, deploy, create ticket — to appear in the dashboard with enough context for guardrails to evaluate it. withTool / with_tool wraps your tool callback, emits telemetry, and optionally evaluates guardrails before execution. When you finish this page, tool calls inside a run will be traced with action and resource metadata.

Basic tool instrumentation

await apie.withRun({ inputSummary: "Process request" }, async (run) => {
  await apie.withTool(
    {
      runId: run.id,
      tool: { name: "search", riskLevel: "low" },
      action: { type: "read", name: "search" },
      resource: { type: "knowledge_base" },
    },
    async () => search("customer billing issue"),
  );
});

What you’ll see

An agent.tool.called event in the run timeline with tool name, action type, resource type, and environment.

Quick start with inference

For monitor mode, you can omit action and resource — Apie infers them from the tool name:
await apie.withTool(
  { runId: run.id, tool: { name: "github.merge_pr" } },
  async () => mergePullRequest(42),
);
// Inferred: action=merge, resource=code_repository, riskLevel=high
Common inference rules:
Tool name patternInferred actionInferred resourceRisk
deploy, releaseexecutedeployment_eventhigh
vault, secretreadsecretcritical
db.update, postgresupdatedatabase_recordhigh
github.mergemergecode_repositoryhigh
search, readreadvarieslow
See Action and resource metadata for the full model and when to override inference.

Production metadata

Before enabling Enforce mode, provide explicit metadata for every risky tool:
await apie.withTool(
  {
    runId: run.id,
    tool: { name: "trigger_pipeline", provider: "cicd", riskLevel: "high" },
    action: { type: "execute", name: "trigger_pipeline" },
    resource: {
      type: "pipeline_run",
      environment: "production",
      externalId: "payments-service",
    },
  },
  async () => cicd.trigger({ service: "payments", dryRun: false }),
);

Guard non-tool actions

For actions that aren’t tool calls — deploying, sending email, modifying config — use withGuard:
await apie.withGuard(
  {
    runId: run.id,
    action: { type: "execute", name: "deploy.release" },
    resource: { type: "deployment_event", environment: "production" },
    riskLevel: "high",
  },
  async () => deployToProduction(),
);

Integration helpers

Framework helpers wrap withTool with sensible defaults:
import { withOpenAIToolCall, withCanonicalToolAction } from "@apie-sh/sdk";

await withOpenAIToolCall(
  apie,
  { runId: run.id, toolName: "search", arguments: { query: "billing" } },
  async () => search("billing"),
);

await withCanonicalToolAction(apie, {
  runId: run.id,
  toolName: "sentry.search_issues",
  provider: "sentry",
  actionType: "read",
  resourceType: "incident",
  environment: "production",
}, async () => { /* tool call */ });

Next steps

Action and resource metadata

Deep dive on the metadata model.

Monitor mode

Observe guardrail evaluations without blocking.