Guardrails
Orçamentos, camadas de política, autoridade com escopo, análise de risco e verificações de raio de destruição — o que detém um agente antes que ele o prejudique.
Cinco guardrails cercam um sandbox de agente de IA. Dois são limites rígidos que o agente fisicamente não pode exceder (LEASH, SCOPE), um transforma dados em um veredito (POLICY), e dois produzem dados para ela pesar (LINT, BLAST). Nenhum coloca um LLM no caminho de confiança.
LEASH — orçamentos por sandbox
Bloqueia: um agente que se descontrola — queimando instruções, compute ou tempo de relógio sem limite.
Defina um orçamento quando você cria ou executa o sandbox:
keon sandbox create \
--budget-statements 500 \
--budget-compute-seconds 120 \
--budget-wall-seconds 900
# or the same three flags on: keon sandbox run …Ao romper o limite, o sandbox autotermina: o status torna-se discarded e
budget_breached nomeia qual limite estourou — statements, compute_seconds ou
wall_clock. A CLI sai com o código de erro sandbox_budget_breached. Um aviso
dispara em 80% de qualquer orçamento.
Na transmissão, os orçamentos são um objeto budgets, uma entrada por orçamento:
"budgets": {
"statements": { "limit": 500, "used": 218, "warned": false },
"compute_seconds": { "limit": 120, "used": 41, "warned": false },
"wall_clock": { "used": 63 }
}Um limit ausente significa ilimitado — não há valor sentinela para
interpretar mal.
Configure padrões e limites máximos (proprietário/administrador):
# Per-project defaults double as the create-time cap.
curl -X PATCH .../v1/projects/{id} \
-d '{"sandbox_budget_defaults": {"statements": 500, "compute_seconds": 120}}'O padrão é o limite máximo: pedir no momento da criação por mais do que o padrão
do projeto retorna 422 sandbox_budget_exceeds_cap. Os padrões por projeto são
configuráveis — não há número fixo para citar aqui.
Duas invariantes:
- Congelado na criação. Os orçamentos são fixados quando o sandbox é criado; mudar os padrões do projeto depois nunca re-restringe um sandbox ativo.
- Chaves de agente apenas apertam. Uma chave de capacidade de agente pode solicitar orçamentos mais apertados na criação; ela nunca pode definir os padrões do projeto.
POLICY — camadas de política de promoção
Bloqueia: um promote cujas mudanças são mais arriscadas do que o projeto permite — mesmo um que um agente (ou um humano) tente deixar passar.
POLICY é uma sobreposição por projeto que mapeia uma classe de risco para uma ação,
disposta em camadas sobre o promote_mode base.
Configure (CLI):
keon projects promote-policy <projectId> # show effective policy
keon projects promote-policy <projectId> \
--set destructive=block \
--set unbounded=require_human \
--on-conflicts require_human # merge-write
keon projects promote-policy <projectId> --clear # drop the overlay--set <class=action> é repetível e mescla na sobreposição existente.
Configure (API): GET / PUT / DELETE /v1/projects/{projectId}/promote-policy:
{ "version": 1,
"rules": { "destructive": "block", "unbounded": "require_human" },
"on_conflicts": "require_human" }| Campo | Valores legais |
|---|---|
| classe de risco | additive, mutating, destructive, unbounded, rewrite |
| ação | auto_promote, require_human, block |
on_conflicts | ignore, require_human, block |
ignore é legal apenas para on_conflicts, nunca como uma ação de classe.
A postura base vem do promote_mode, e a sobreposição substitui por classe:
promote_mode | Toda classe usa como padrão |
|---|---|
self | auto_promote |
human | require_human |
Cada regra efetiva reporta de onde veio — source: overlay,
promote_mode ou default.
O que o agente vê quando bloqueado: um promote bloqueado retorna
409 promote_blocked_by_policy com os detalhes da decisão anexados.
Regra-chave: um Approve humano nunca pode substituir um block de política. A política
é reavaliada no momento do approve, então block se mantém contra o clique. A validação de
política é à prova de falhas / estrita — uma política que não pode ser analisada nega, ela nunca
degrada para aberta.
SCOPE — autoridade com escopo (faixas)
Bloqueia: qualquer leitura ou gravação fora dos esquemas e tabelas que você declarou — a faixa do agente.
Configure (apenas no momento da criação):
keon sandbox create \
--schemas app,analytics \
--tables app.users,app.orders
# omit both flags → unscoped (full-branch authority)--tables sem --schemas é rejeitado no cliente como invalid_lane.
Dentro da bifurcação o agente fisicamente não pode gravar fora da faixa — uma
gravação fora da faixa falha na bifurcação com o SQLSTATE 42501 (privilégio insuficiente)
ou 3F000 (nome de esquema inválido). Leituras fora da faixa também são negadas. E o
promote recusa qualquer mudança fora da faixa com 409 sandbox_out_of_lane.
Na transmissão, o sandbox carrega um objeto scope (ausente = sem escopo):
"scope": { "v": 1, "schemas": ["app", "analytics"], "tables": ["app.users", "app.orders"] }keon sandbox diff ganha um objeto lane que lista quaisquer violations[], cada uma com
um motivo — out_of_lane_schema, out_of_lane_relation ou
unresolvable_targets.
Dois limites:
- Imutável após a criação. Ampliar uma faixa significa descartar + recriar — não há ampliação no lugar.
- Apenas alvos diretos. Uma faixa não governa efeitos colaterais transitivos
alcançados por triggers ou funções
SECURITY DEFINER.
LINT — classificação estática de risco
Produz: uma classe estática de risco para cada instrução no conjunto de replay — sem execução, sem LLM, sem contagens de linhas. Puramente textual.
Não há novo comando. LINT aparece em três lugares que você já lê:
- dentro de
keon sandbox diffcomorisk_report, - por ação em
keon sandbox log, - como
max_risk_classna transmissão do sandbox.
Classes, da menor à maior severidade:
additive < mutating < rewrite < unbounded < destructiveUm conjunto de replay vazio é classificado como none.
Formato do relatório:
{ "statements": [
{ "seq": 4, "risk_class": "unbounded",
"reasons": ["where_trivially_true: DELETE guarded by WHERE 1=1 matches every row"] }
],
"rollup": { "max_class": "unbounded", "counts": { "additive": 2, "unbounded": 1 } } }Cada motivo é <snake_case_code>: <sentence>. Por exemplo, WHERE true ou
WHERE 1=1 classifica a instrução como unbounded com o motivo
where_trivially_true.
Duas coisas a lembrar:
- LINT é dado, não uma decisão. Ele classifica; POLICY impõe. LINT nunca bloqueia nada por conta própria.
- Ele falha para cima. Sob incerteza LINT atribui a pior classe plausível.
Como a detecção é textual, as contagens de linhas reais não são uma entrada — um
DELETEsemWHEREé lido comodestructivequer a tabela tenha uma linha ou um bilhão.
BLAST — ensaio do raio de destruição
Produz: evidência medida do que um promote realmente faria — níveis de lock reais, durações de retenção de lock reais, contagens de linhas reais e qualquer divergência desde a bifurcação.
keon sandbox dry-run <id>Ele reexecuta o conjunto exato de instruções do sandbox contra duas bifurcações descartáveis do
pai, mede o custo real, detecta divergência, depois destrói ambas. Ele
nunca toca em main, e o agente nunca recebe uma credencial de bifurcação.
BLAST é consultivo — ele nunca bloqueia um promote; conflitos são expostos como
dados.
A referência completa de campos, a semântica de conflitos e a lista de endpoints vivem em Sandboxes & promote → Ensaio do raio de destruição.
Como eles se encaixam
- LINT e BLAST produzem dados — um estático, um medido.
- POLICY transforma esses dados em uma decisão, à prova de falhas, não substituível por um
clique humano quando ela diz
block. - LEASH e SCOPE são limites rígidos que o agente não pode exceder de forma alguma — impostos na bifurcação, congelados na criação.
Veja Armadilhas comuns para as maneiras como esses cinco são rotineiramente mal interpretados.
Sandboxes & promote
Aponte um agente de programação de IA para seu banco de dados de produção com segurança — capturado, observado, promovido por um portão e reversível.
Bifurcações mascaradas
Dê a um agente (ou a um humano) o formato da produção e nada da sua PII — políticas de mascaramento, a biblioteca de funções embutidas e como branches e sandboxes mascarados permanecem selados até o mascaramento ser confirmado.