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:
Layer Question it answers Example Tool Which capability was invoked? { name: "github.merge_pr", provider: "github", riskLevel: "high" }Action What operation was performed? { type: "merge", name: "github.merge_pr" }Resource What was affected? { type: "code_repository", environment: "production", externalId: "acme/api" }
Action types
Type Use 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
Type Examples 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
In monitor mode, omit action and resource and Apie infers defaults from the tool name:
Tool name contains Inferred action Inferred resource Risk deploy, releaseexecutedeployment_eventhigh vault, secretreadsecretcritical db, postgres, sqlupdatedatabase_recordhigh merge, githubmergecode_repositoryhigh pipeline, cicdexecutepipeline_runhigh search, read, getreadvaries low 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 }),
);
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.