Skip to content

Agent guards testing and reference

Test at the action boundary and assert both the decision behavior and the side effect. For each guarded tool, cover:

ScenarioExpected result
Allowed actor and inputsTool executes once
Policy rule denial in LIVETool does not execute
Same rule in DRY_RUNResult is recorded, but the rule does not block
Missing or wrong typed inputPolicy is incomplete; sensitive tools do not execute
Guard transport or evaluation failureYour selected fail behavior is applied
Local sensitive valueRaw local string is not sent as a policy input

Use deterministic inputs for each rule: a recipient outside an allowed list, a string outside the configured byte-length range, known sensitive test data, and a clear prompt-injection fixture. Review policyResults / policy_results to identify the specific remote rule that matched.

DRY_RUN is useful for evaluating a policy against real calls before enabling enforcement, but it does not replace a test that proves the side effect is skipped on a LIVE denial.

const decision = await arcjet.guard({
label: "email.sent",
actor: user.id,
inputs: {
recipient: policyInput.server.string(to),
},
rules: [],
metadata: { workflow: "support" },
correlationId: runId,
timeoutSeconds: 2,
signal,
});
OptionDescription
labelRequired action identifier and remote-policy selector
actorOptional trusted, application-asserted identity
inputsNamed values created with policyInput.server.* or policyInput.local.*
rulesOptional SDK rule submissions; an empty list still calls Guard
metadataStructured analytics and debugging context
correlationIdIdentifier shared across related calls
timeoutSecondsGuard request timeout; defaults to 2 seconds
signalOptional cancellation signal

Every decision has an id, conclusion, SDK results, warnings, and error accessors. A denial also has a broad reason. Remote policy status and results are additive and may be absent when the server does not provide policy data.

Remote policy data is separate from SDK-submitted rule results:

  • policyResults / policy_results contains keyed remote rule results with policy ID, revision, rule ID, LIVE or DRY_RUN mode, SDK or SERVER execution, and the typed result.
  • results remains the positional list for rules submitted by the SDK call.

The Arcjet server combines enforced SDK and remote rules into the final ALLOW or DENY; the SDK does not recompute that aggregate conclusion.

policyEvaluation / policy_evaluation reports which policy revision Arcjet evaluated and its status:

StatusWhat it meansWhen you may see itHow to handle it
NOT_CONFIGUREDNo published remote policy matched the guard label.A label intentionally has no policy, the label is wrong, or the policy has not been published.If a policy is expected, verify the label and publish it. Otherwise handle the SDK rule decision normally.
APPLIEDArcjet completely evaluated the matching remote policy.The supplied actor and inputs satisfy the policy contract and all required evaluation is available.Enforce the returned ALLOW or DENY conclusion.
INCOMPLETEA matching policy could not be completely evaluated.A required actor or input is missing or invalid, or required local evaluation could not complete.Treat the security check as incomplete and apply your chosen availability behavior.
UNAVAILABLERemote policy evaluation was temporarily unavailable.Arcjet could not complete a required policy evaluation.Retry where appropriate or apply your chosen availability behavior.
UNKNOWNThe SDK does not recognize the policy status from Arcjet.A newer server returns a status this SDK version does not understand.Upgrade the SDK and, until then, treat the security check as incomplete.

The field may be absent when the server does not return remote-policy status. If your application expects a policy, inspect the decision’s error results and verify the SDK and policy configuration.

The direct Guard client fails open when a transport, timeout, response, local evaluation, or remote-policy completeness error prevents a full evaluation. It returns ALLOW with an error result instead of treating the incomplete check as a policy denial.

if (decision.conclusion === "DENY" || decision.hasFailedOpen()) {
throw new Error("Action blocked");
}

Use decision.errorResults() for diagnostics.

Agent framework wrappers have a stricter default: the wrapped tool does not execute on either a real DENY or unavailable evaluation. Use onGuardError: "allow" / on_guard_error="allow" to opt a wrapper into execution when the security check cannot be completed.

Warnings are informational and do not mean the decision failed open. Log them to correct request data, but do not treat a warning alone as a denial.