Skip to main content
Guardrails need to know what your agent is doing and what it’s touching — not just the tool name. The action describes the operation. The resource describes the target. Together they power boundary maps, risk scoring, and policy evaluation. When you finish this page, you’ll know how to model tool calls for Monitor mode (inference) and Enforce mode (explicit metadata).

The three layers

Every instrumented tool call has three layers of metadata:
LayerQuestion it answersExample
ToolWhich capability was invoked?{ name: "github.merge_pr", provider: "github", riskLevel: "high" }
ActionWhat operation was performed?{ type: "merge", name: "github.merge_pr" }
ResourceWhat was affected?{ type: "code_repository", environment: "production", externalId: "acme/api" }

Action types

TypeUse when the agent…
readFetches or queries data
createCreates a new resource
updateModifies an existing resource
deleteRemoves a resource
executeRuns a command, deploy, or pipeline
communicateSends a message, email, or notification
mergeMerges code, branches, or pull requests

Resource types

TypeExamples
code_repositoryGitHub repos, GitLab projects
deployment_eventProduction deploys, rollbacks
pipeline_runCI/CD pipeline executions
secretVault entries, API keys
work_itemTickets, issues, tasks
database_recordDatabase rows, collections
fileFilesystem paths
observability_eventLogs, metrics, traces
shell_commandArbitrary shell execution
incidentOn-call incidents, alerts

Inference from tool names

In monitor mode, omit action and resource and Apie infers defaults from the tool name:
Tool name containsInferred actionInferred resourceRisk
deploy, releaseexecutedeployment_eventhigh
vault, secretreadsecretcritical
db, postgres, sqlupdatedatabase_recordhigh
merge, githubmergecode_repositoryhigh
pipeline, cicdexecutepipeline_runhigh
search, read, getreadvarieslow
rm, delete, destroydeleteshell_commandcritical
Enable inference in config:
boundary: { autoInferFromToolNames: true }
In JavaScript, inferFromToolName() is exported from @apie-sh/sdk. In Python, inference runs inside with_tool when metadata is omitted.

When to override inference

Override with explicit metadata when:
  • Moving from Monitor mode to Enforce mode
  • Tool names are ambiguous (process could be read or execute)
  • You need environment-specific policies (production vs staging)
  • Compliance requires auditable resource targets (externalId)

Production example

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",
      provider: "cicd",
    },
  },
  async () => cicd.trigger({ service: "payments", dryRun: false }),
);

Platform connectors

Use canonical helpers for common platforms — they set provider and resource defaults:
import { withGitHubAction, withIncidentResponseAction } from "@apie-sh/sdk";

await withGitHubAction(apie, {
  runId: run.id,
  actionType: "merge",
  resourceTarget: "acme/api",
  environment: "production",
}, async () => github.mergePr(42));

await withIncidentResponseAction(apie, {
  runId: run.id,
  actionType: "execute",
  provider: "pagerduty",
}, async () => pagerduty.page("on-call"));
See Platform connectors.

Next steps

Monitor mode

Observe guard evaluations with inferred metadata.

Enforce guardrails

Switch to Enforce mode with explicit metadata.