faramesh.devBETA
docsgithubcommunityget started →

docs

Getting Started

Core

FPL

Governance

Operations

Reference

github ↗slack ↗community ↗

FPL language reference

FPL Syntax Reference

This is the complete language reference for FPL (Faramesh Policy Language). It documents every keyword, operator, block type, and syntax construct. FPL files use the .fpl extension.

File structure

An FPL file contains one or more agent blocks. Each agent block defines a complete policy for a single agent identity. Comments start with # and extend to the end of the line.

structure.fplfpl
# This is a comment
agent my-agent {
  # ... blocks and rules go here
}

agent another-agent {
  # multiple agents in one file are allowed
}

Keywords

All reserved keywords in FPL. Keywords are case-sensitive and always lowercase (except deny!).

KEYWORDCONTEXTMEANING
agenttop-levelDeclares an agent policy block. Takes a name identifier.
defaultagentSets the default verdict when no rule matches. Value: permit or deny.
modelagentConstrains which LLM model this agent may use. Value: string.
frameworkagentDeclares the expected agent framework. Value: string.
budgetagentOpens a budget block. Qualifier: session or daily.
maxbudgetMaximum cost limit. Value: dollar amount (e.g. $500).
dailybudgetDaily rolling cost limit. Value: dollar amount.
max_callsbudgetMaximum number of tool calls. Value: integer.
on_exceedbudgetWhat happens when budget is exceeded. Value: deny or defer.
phaseagentOpens a workflow phase block. Takes a phase name.
rulesagentOpens the global rules block.
permitrules/phaseAllow a tool call. Takes a tool pattern.
denyrules/phaseBlock a tool call. Takes a tool pattern.
deny!rules/phaseMandatory deny. Compile-time enforced, cannot be overridden.
deferrules/phaseHold a tool call for human approval. Takes a tool pattern.
whenruleConditional clause. Followed by a condition expression.
reason:ruleHuman-readable reason string attached to the verdict.
notify:ruleWho to notify on defer. Value: string (team/channel name).
reeval:ruleWhether to re-evaluate after approval. Value: true or false.
delegateagentOpens a delegation block. Takes a delegate name.
scopedelegateWhich tools the delegate may use. Value: tool pattern or quoted string.
ceilingdelegateMaximum budget the delegate may use. Value: inherited or number.
ttldelegateTime-to-live for the delegation token. Value: duration (e.g. 1h, 30m).
ambientagentOpens the ambient credential stripping block.
stripambientAn environment variable to remove from the agent process.
selectoragentOpens a selector block for external data binding.
sourceselectorURL of the external data source.
cacheselectorCache TTL for selector data. Value: duration.
bindselectorVariable name to bind the result to in policy context.
credentialagentOpens a credential broker binding block. Takes a credential name.
backendcredentialSecret backend to use. Value: vault, aws, gcp, azure, 1password, infisical.
pathcredentialPath to the secret in the backend.
fieldcredentialSpecific field within the secret to extract.

Tool patterns

Tool patterns match tool call names. They support exact match and wildcard (*) matching.

PATTERNMATCHES
shell/runExact match: only shell/run.
shell/*Wildcard: shell/run, shell/exec, shell/anything.
stripe/refundExact match: only stripe/refund.
stripe/*Wildcard: stripe/refund, stripe/charge, stripe/anything.
*Matches all tools. Use in default or catch-all rules.
api/v2/*Wildcard on nested paths: api/v2/users, api/v2/orders.

Condition expressions

The when clause accepts condition expressions. Conditions reference tool call arguments and policy context variables.

OPERATOREXAMPLEDESCRIPTION
>amount > 500Greater than. Numeric comparison.
<amount < 100Less than. Numeric comparison.
>=amount >= 500Greater than or equal.
<=amount <= 100Less than or equal.
==status == "active"Equality. Works with strings and numbers.
!=status != "blocked"Not equal.
matchescmd matches "rm -rf|DROP"Regex match against a pipe-delimited pattern.
andamount > 500 and risk > 0.8Logical AND. Both conditions must be true.
oramount > 1000 or risk > 0.9Logical OR. Either condition must be true.

Conditions can reference these built-in variables:

VARIABLEDESCRIPTION
amountNumeric argument named 'amount' from the tool call.
cmdString argument named 'cmd' from the tool call.
recipientsNumeric argument (e.g. number of email recipients).
riskNumeric risk score, typically from a selector binding.
pathFile path argument from the tool call.
tool_nameThe name of the tool being called.
session.sum(tool, window)Aggregate function: sum of a field across calls within a time window.
session.count(tool, window)Aggregate function: count of calls within a time window.
selectors.<name>.<field>External data bound via a selector block.

Effects (verdicts)

Every rule produces one of four effects. Rules are evaluated top to bottom , first match wins.

EFFECTBEHAVIOR
permitThe action is allowed. If a credential is needed, it is issued from the broker.
denyThe action is blocked. The agent receives a DENY verdict with the reason string.
deny!Mandatory deny. Same as deny but enforced at compile time , no child policy, extends, or priority can override it. This is the strongest guarantee in FPL.
deferThe action is held for human approval. The agent pauses. Nothing runs until someone approves or denies.

Rule syntax

Rules follow this structure. All clauses after the tool pattern are optional.

rule syntaxfpl
# Minimal rule — no condition
permit search/*

# Rule with condition
deny shell/run when cmd matches "rm -rf"

# Rule with condition + reason
deny! shell/run
  when cmd matches "rm -rf|DROP TABLE"
  reason: "destructive command blocked"

# Defer with condition + notify + reason
defer payment/transfer
  when amount > 1000
  notify: "finance-team"
  reason: "high value transfer"
  reeval: true

# Aggregate condition
deny stripe/refund
  when session.sum(stripe/refund.amount, window=1h) > 2000
  reason: "aggregate refund limit exceeded"

agent block

The top-level container. Everything else lives inside it.

agentfpl
agent <name> {
  default deny        # or permit
  model   "gpt-4o"     # optional
  framework "langgraph" # optional
  # ... budget, phase, rules, delegate, ambient, selector, credential blocks
}

budget block

Sets spending and call limits for the session. When exceeded, all subsequent calls are denied (or deferred, depending on on_exceed).

budgetfpl
budget session {
  max       $500    # max cost per session
  daily     $2000   # daily rolling limit
  max_calls 100     # max tool calls per session
  on_exceed deny    # deny or defer
}

phase block

Defines a workflow phase with its own permit/deny/defer rules. Only one phase is active at a time. The agent or operator transitions between phases.

phasefpl
phase intake {
  permit read_customer
  permit get_order
  permit search_kb
}

phase resolve {
  permit issue_credit when amount <= 25
  defer  issue_credit when amount > 25
    notify: "support-lead"
}

rules block

Global rules applied regardless of the active phase. Evaluated top to bottom , first match wins.

rulesfpl
rules {
  deny! shell/* reason: "no shell access"
  deny! fs/write when path matches "/etc|/usr|/bin"
  defer payment/* when amount > 500
    notify: "finance"
  permit api/*
  permit search/*
}

delegate block

Grants a sub-agent a subset of permissions. Monotonic narrowing: the delegate can never exceed the delegator's scope.

delegatefpl
delegate research-worker {
  scope   "search/*"   # tools the delegate may call
  ttl     1h           # delegation expires after 1 hour
  ceiling inherited    # budget ceiling from parent
}

ambient block

Lists environment variables to strip from the agent process before it starts. The agent never sees these values.

ambientfpl
ambient {
  strip OPENAI_API_KEY
  strip STRIPE_API_KEY
  strip AWS_SECRET_ACCESS_KEY
}

selector block

Binds external data (risk scores, feature flags, user attributes) into the policy context. The data is fetched at decision time and cached.

selectorfpl
selector fraud-score {
  source "https://risk.internal/api/score"
  cache  30s
  bind   ctx.fraud_score
}

Use in rules: when selectors.fraud-score.score > 0.8

credential block

Binds a named credential to a secret backend. The broker issues the credential only when the policy permits the tool call.

credentialfpl
credential stripe {
  backend vault              # vault | aws | gcp | azure | 1password | infisical
  path    secret/data/stripe/live
  field   api_key            # specific field in the secret
  ttl     15m                # credential lease duration
}

Duration values

Durations are used in ttl, cache, and window fields.

SUFFIXMEANING
sSeconds. Example: 30s
mMinutes. Example: 15m
hHours. Example: 1h, 24h
dDays. Example: 7d, 30d

Dollar values

Cost fields accept dollar-prefixed values. The $ is part of the syntax.

dollar valuesfpl
max       $500     # integer
daily     $2000    # integer
max_cost  $50.00   # decimal

Evaluation order

Understanding rule evaluation order is essential to writing correct policies.

1The daemon receives a tool call and identifies the agent.
2If a kill switch is active for the agent, the call is denied immediately.
3If the session budget is exhausted, the call is denied.
4If the current phase has rules for this tool, those are evaluated first. First match wins.
5If no phase rule matched, the global rules block is evaluated. First match wins.
6If no rule matched anywhere, the default effect applies (permit or deny).
7deny! rules are enforced across all of the above , they cannot be overridden by any other rule.

CLI commands for FPL

COMMANDWHAT IT DOES
faramesh policy validate agent.fplCheck for syntax and semantic errors. Exit code 0 if valid.
faramesh policy inspect agent.fplPrint a summary of all rules, phases, and blocks.
faramesh policy compile "deny shell"Compile natural language to FPL.
faramesh policy fpl decompile policy.yamlConvert YAML back to FPL.
faramesh policy diff a.fpl b.fplShow differences between two FPL files.
faramesh policy backtest agent.fplReplay policy against historical DPR records.
faramesh policy suite policy.yaml --fixtures suite.yamlRun a policy test suite.
faramesh policy cover agent.fplShow coverage: which rules matched during backtesting.

Complete example

A production-ready FPL policy using all major constructs.

production.fplfpl
agent payment-bot {
  default deny
  model   "gpt-4o"
  framework "langgraph"

  budget session {
    max       $500
    daily     $2000
    max_calls 100
    on_exceed deny
  }

  phase intake {
    permit read_customer
    permit get_order
  }

  phase resolve {
    permit stripe/charge when amount <= 500
    defer  stripe/refund when amount > 500
      notify: "finance"
      reason: "high value refund"
  }

  rules {
    deny! shell/* reason: "no shell access"
    deny! fs/write when path matches "/etc|/usr"
    deny  stripe/refund
      when session.sum(stripe/refund.amount, window=1h) > 2000
      reason: "aggregate refund limit"
  }

  delegate finance-reviewer {
    scope   "stripe/refund"
    ceiling inherited
    ttl     4h
  }

  ambient {
    strip OPENAI_API_KEY
    strip STRIPE_API_KEY
  }

  selector risk {
    source "https://risk.internal/api/score"
    cache  30s
    bind   ctx.risk_score
  }

  credential stripe {
    backend vault
    path    secret/data/stripe/live
    field   api_key
    ttl     15m
  }
}

Save this as policy.fpl and run faramesh policy validate policy.fpl to check for errors. Every keyword and block in this example is documented above.

Need help? Use any of these support options.

open an issuejoin slackcommunity/forum
MIT License
docsgithubcommunityget started →