Black Friday: 79% off every plugin Shop the sale →

Guardrails API

Plugins that do not use abilities can still route their own actions through the same approval, snapshot and audit engine. Register an action once, then run it with ankgr_run().

add_action( 'ankgr_loaded', function () {
	ankgr_register_action(
		'my-plugin/refund-order',
		array(
			'label'      => 'Refund an order',
			'capability' => 'manage_woocommerce',
			'risk'       => 'critical', // low, medium, high or critical.
			'execute'    => function ( $input ) {
				return my_plugin_refund( (int) $input['order_id'], (float) $input['amount'] );
			},
		)
	);
} );

$result = ankgr_run(
	'my-plugin/refund-order',
	array( 'order_id' => 123, 'amount' => 10.0 ),
	array( 'origin' => 'my-plugin' )
);

if ( is_wp_error( $result ) && 'ankgr_pending_approval' === $result->get_error_code() ) {
	// Held: the request now waits in Agent Control > Approvals.
}

Functions#

FunctionWhat it does
ankgr()Returns the engine (AnkGR_Engine).
ankgr_register_action( $name, $args )Registers an action. $args: label, description, capability, risk (low, medium, high, critical), execute (callable, required), optional preview and summarize callables.
ankgr_run( $action, $input, $context )Runs an action through policy. Allow runs it with a snapshot; approve returns WP_Error( 'ankgr_pending_approval' ) (409); deny returns ankgr_denied (403). $context: credential_type, credential_id, credential_label, transport, origin. Unknown actions return ankgr_unknown_action (404); a user without the capability gets ankgr_forbidden (403).
ankgr_get_request( $id_or_uuid )Returns an AnkGR_Request or null.
ankgr_approve( $id, $user_id = 0 )Approves a pending request and runs it as the user who made it.
ankgr_reject( $id, $user_id = 0, $reason = '' )Rejects a pending request.
ankgr_rollback( $id, $force = false, $ack_external = false )Rolls a request back as a new recorded request. $force overwrites drift; $ack_external accepts that external effects are not undone.
ankgr_log( $event, $data )Writes an audit event (data is redacted).
ankgr_schedule_maintenance() / ankgr_unschedule()Schedule or clear the hourly maintenance job. Call ankgr_unschedule() from your plugin’s deactivation hook.

Plugging in your own policy#

The engine’s default decision is “allow”. Hosts decide through a filter:

add_filter( 'ankgr_policy_decision', function ( $decision, $request ) {
	if ( 'my-plugin/refund-order' === $request->action && 'cli' === $request->credential_type ) {
		$request->decision_reason = 'Refunds from the command line need approval.';
		return 'approve';
	}
	return $decision;
}, 20, 2 );
Was this article helpful?