Rego — 18 Operations for AI Agents
Rego is policy as code: OPA admission control, authorization decisions, compliance gates across Kubernetes and CI. act101 lets agents navigate policies structurally, finding the rule that allowed or denied a request without re-reading the bundle.
This page is the canonical reference an AI coding agent uses to refactor, query, and analyze Rego code through the act MCP server. 18 operations available: 0 refactor, 18 query, 0 analysis. Each operation is callable from Claude Code, Cursor, Codex, OpenCode, or any MCP-compatible agent host. Click any operation for a stable anchor link suitable for citation.
Worked Rego examples
act101 reads a Rego file's package declaration, each import statement, and every rule definition as declarations. The skeleton tags the package a module, named for its dotted path; tags each rule clause function, named for the rule — a rule with more than one clause, like a default value alongside its full body, reports one function declaration per clause, all sharing the rule's name; and tags each import statement import, but names it literally "import" in every case, since the rule captures only the bare import keyword and never reaches for the sibling node holding the actual imported path. symbols covers the package and every rule clause but has no rule for import at all, so it drops the import entirely rather than repeating its useless name. The unit of structure in this grammar is the top-level statement: neither query descends into a rule's own body conditions. Each example below is the verbatim output of the command shown, run against the file shown. Query outputs are pretty-printed with the timing block omitted.
Read the badge-access policy's package, import, and rules as a skeleton
badge-access.rego declares the physical.badge_access package, imports future.keywords.in, and defines allow (a default clause plus a full clause), after_hours, and deny_reason.
$ act query skeleton badge-access.rego
Before
package physical.badge_access
import future.keywords.in
default allow := false
allow if {
input.employee.clearance_level >= input.door.required_level
input.employee.department in input.door.allowed_departments
}
after_hours if {
input.request_time.hour < 6
}
deny_reason contains "outside authorized hours" if {
after_hours
not input.employee.on_call
}
Output
{
"type": "Skeleton",
"declarations": [
{
"kind": "module",
"name": "physical.badge_access",
"range": {
"start": {
"file": "badge-access.rego",
"line": 1,
"column": 1,
"byte_offset": 0
},
"end": {
"file": "badge-access.rego",
"line": 19,
"column": 2,
"byte_offset": 362
}
},
"name_range": {
"start": {
"file": "badge-access.rego",
"line": 1,
"column": 9,
"byte_offset": 8
},
"end": {
"file": "badge-access.rego",
"line": 1,
"column": 30,
"byte_offset": 29
}
}
},
{
"kind": "import",
"name": "import",
"range": {
"start": {
"file": "badge-access.rego",
"line": 3,
"column": 1,
"byte_offset": 31
},
"end": {
"file": "badge-access.rego",
"line": 3,
"column": 7,
"byte_offset": 37
}
}
},
{
"kind": "function",
"name": "allow",
"range": {
"start": {
"file": "badge-access.rego",
"line": 5,
"column": 1,
"byte_offset": 58
},
"end": {
"file": "badge-access.rego",
"line": 5,
"column": 23,
"byte_offset": 80
}
},
"name_range": {
"start": {
"file": "badge-access.rego",
"line": 5,
"column": 9,
"byte_offset": 66
},
"end": {
"file": "badge-access.rego",
"line": 5,
"column": 14,
"byte_offset": 71
}
}
},
{
"kind": "function",
"name": "allow",
"range": {
"start": {
"file": "badge-access.rego",
"line": 7,
"column": 1,
"byte_offset": 82
},
"end": {
"file": "badge-access.rego",
"line": 10,
"column": 2,
"byte_offset": 216
}
},
"name_range": {
"start": {
"file": "badge-access.rego",
"line": 7,
"column": 1,
"byte_offset": 82
},
"end": {
"file": "badge-access.rego",
"line": 7,
"column": 6,
"byte_offset": 87
}
}
},
{
"kind": "function",
"name": "after_hours",
"range": {
"start": {
"file": "badge-access.rego",
"line": 12,
"column": 1,
"byte_offset": 218
},
"end": {
"file": "badge-access.rego",
"line": 14,
"column": 2,
"byte_offset": 265
}
},
"name_range": {
"start": {
"file": "badge-access.rego",
"line": 12,
"column": 1,
"byte_offset": 218
},
"end": {
"file": "badge-access.rego",
"line": 12,
"column": 12,
"byte_offset": 229
}
}
},
{
"kind": "function",
"name": "deny_reason",
"range": {
"start": {
"file": "badge-access.rego",
"line": 16,
"column": 1,
"byte_offset": 267
},
"end": {
"file": "badge-access.rego",
"line": 19,
"column": 2,
"byte_offset": 362
}
},
"name_range": {
"start": {
"file": "badge-access.rego",
"line": 16,
"column": 1,
"byte_offset": 267
},
"end": {
"file": "badge-access.rego",
"line": 16,
"column": 12,
"byte_offset": 278
}
}
}
]
}
The skeleton reports six declarations: the package as module, the import as import named literally "import" rather than future.keywords.in, allow twice — once for its default clause and once for its full if clause — and after_hours and deny_reason once each, all function.
List the package and rule clauses as symbols
The same file has one package and four rule clauses; the import statement is not a rule.
$ act query symbols badge-access.rego
Before
package physical.badge_access
import future.keywords.in
default allow := false
allow if {
input.employee.clearance_level >= input.door.required_level
input.employee.department in input.door.allowed_departments
}
after_hours if {
input.request_time.hour < 6
}
deny_reason contains "outside authorized hours" if {
after_hours
not input.employee.on_call
}
Output
{
"type": "Symbols",
"symbols": [
{
"name": "physical.badge_access",
"kind": "module",
"range": {
"start": {
"file": "badge-access.rego",
"line": 1,
"column": 9,
"byte_offset": 8
},
"end": {
"file": "badge-access.rego",
"line": 1,
"column": 30,
"byte_offset": 29
}
},
"visibility": "unknown"
},
{
"name": "allow",
"kind": "function",
"range": {
"start": {
"file": "badge-access.rego",
"line": 5,
"column": 9,
"byte_offset": 66
},
"end": {
"file": "badge-access.rego",
"line": 5,
"column": 14,
"byte_offset": 71
}
},
"visibility": "unknown"
},
{
"name": "allow",
"kind": "function",
"range": {
"start": {
"file": "badge-access.rego",
"line": 7,
"column": 1,
"byte_offset": 82
},
"end": {
"file": "badge-access.rego",
"line": 7,
"column": 6,
"byte_offset": 87
}
},
"visibility": "unknown"
},
{
"name": "after_hours",
"kind": "function",
"range": {
"start": {
"file": "badge-access.rego",
"line": 12,
"column": 1,
"byte_offset": 218
},
"end": {
"file": "badge-access.rego",
"line": 12,
"column": 12,
"byte_offset": 229
}
},
"visibility": "unknown"
},
{
"name": "deny_reason",
"kind": "function",
"range": {
"start": {
"file": "badge-access.rego",
"line": 16,
"column": 1,
"byte_offset": 267
},
"end": {
"file": "badge-access.rego",
"line": 16,
"column": 12,
"byte_offset": 278
}
},
"visibility": "unknown"
}
]
}
symbols reports five entries — physical.badge_access as module and the same four rule clauses as function — dropping the import that skeleton listed.
Query
18 query tools, the same on every supported language. Descriptions live in the shared reference: /docs/query-tools.
callers control_flow data_flow definition diagnostics effect_closure effect_summary fix_auto get_type graph import_organize interface mutations references repo_outline skeleton symbols symbols_batch