Tutorial: Safety-Guarded Goals¶
This tutorial shows how to run agent goals with CSF (Computational Safety Framework) safety guards, so G6 checks modeled risk before execution and pauses for a human when it matters. You drive everything through G6's surfaces — the GUI, Claude Code (MCP), or REST — by attaching declarative controls to your goal. No coding required.
Use CSF as a gate, not a guarantee
CSF decisions are based on configured hazard priors and an epsilon budget. They help block obviously risky or over-budget actions and create an audit trail, but they do not certify real-world safety. For high-stakes or regulated workflows, add human review, domain-specific tests, and compliance review.
What you will build¶
A safety-guarded goal that:
- Declares resource bounds (token / time / cost limits) for the run
- Adds a guardrail that halts if a modeled CSF hazard exceeds its budget
- Adds a checkpoint that logs a quality metric without halting
- Adds a breakpoint that pauses for human approval before a high-stakes step
- Lets you review the safety decision that G6 records for the run
How CSF decides¶
G6 ships with default hazard priors and a safety threshold (epsilon). You can see them any time by asking G6 for its safety status (the system_status tool reports the active CSF signature):
| Hazard | Default prior |
|---|---|
llm_call | 0.05 (5%) |
file_write | 0.01 (1%) |
code_execute | 0.10 (10%) |
external_api | 0.08 (8%) |
rollback | 0.001 (0.1%) |
The epsilon budget (default 0.20) is the maximum acceptable combined hazard. A plan is approved by the gate when its modeled hazard stays under epsilon. Two strategies are available:
| Strategy | Formula | Conservatism |
|---|---|---|
union_bound | sum(hazards) < epsilon | Moderate — sum of all hazard probabilities |
worst_case | max(hazards) < epsilon | High — even a single high hazard can block |
So a step that calls an LLM (0.05) and an external API (0.08) has a combined bound of 0.13 < 0.20 → approved. Add code execution (0.10) and file writes (0.01) and the bound becomes 0.24 > 0.20 → blocked.
Step 1: Declare safety controls on your goal¶
G6 reads three kinds of declarative control from your goal's JSON. These are evaluated by the engine at runtime — you don't write Python:
| Control | Behaviour |
|---|---|
| Guardrail | Hard constraint — halts execution on violation |
| Checkpoint | Soft assertion — evaluated and logged, does not halt |
| Breakpoint | HITL pause — stops execution and waits for human review |
A goal with all three:
{
"goal": "Train and deploy an ML classifier",
"resource_bounds": {
"max_execution_seconds": 600,
"max_tokens_per_hour": 200000
},
"guardrails": [
{
"name": "csf_code_execute",
"predicate": "csf_hazard",
"params": {"action": "code_execute", "max_prob": 0.10},
"message": "Halt if code-execution hazard exceeds 10%"
}
],
"checkpoints": [
{
"name": "f1_quality_gate",
"predicate": "metric_above",
"params": {"metric": "f1", "threshold": 0.90},
"description": "Log a warning if F1 drops below 0.90"
}
],
"breakpoints": [
{
"name": "pre_deploy_review",
"description": "Pause for human review before deploying to production",
"active": true
}
],
"subtasks": []
}
Predicate registry¶
Each guardrail and checkpoint references a predicate key:
| Predicate Key | Description | Params |
|---|---|---|
resource_limit | Checks token/disk usage against limits | max_tokens_per_hour, max_disk_bytes |
metric_above | Checks that a metric exceeds a threshold | metric, threshold |
metric_below | Checks that a metric is below a threshold | metric, threshold |
csf_hazard | Checks CSF hazard probability for an action type | action, max_prob |
always_true | No-op — always passes | (none) |
always_pause | Always triggers — useful for unconditional breakpoints | (none) |
Step 2: Run the goal with safety verification¶
Submit the goal through whichever surface you use — the controls travel with it and the engine enforces them.
Ask your assistant to run a safety-verified pipeline. It calls the run_safety_pipeline tool, which runs the goal through CSF verification before execution:
Use the G6 run_safety_pipeline tool to run this goal with its guardrails,
checkpoints, and breakpoints: <paste the goal JSON above>
For a quick check without running anything, ask:
Open the Dashboard, choose Create a run, and paste your goal (including the guardrails / checkpoints / breakpoints). G6 verifies safety before each step. When a breakpoint fires, the run appears in the Approvals view for you to approve or reject.
Submit the goal to the REST API (run it as a self-hosted server). The safety pipeline is reachable through component invocation:
curl -X POST http://localhost:8000/invoke/csf \
-H "Content-Type: application/json" \
-d '{"operation": "verify", "params": {"hazards": {"llm_call": 0.05, "external_api": 0.08}, "epsilon": 0.20, "strategy": "union_bound"}}'
See REST Endpoints for the full request/response schema.
Step 3: Review the safety decision¶
Every safety check returns a structured decision you can inspect (in the tool result, the GUI run summary, or the REST response):
{
"is_safe": true,
"bound_value": 0.13,
"strategy": "union_bound",
"details": {
"hazards": {"llm_call": 0.05, "external_api": 0.08},
"epsilon": 0.20,
"combined_bound": 0.13,
"margin": 0.07
}
}
If the combined bound exceeds epsilon, is_safe is false and the guarded step does not run — the decision and its reason are recorded in the run's audit trail.
When to use which control¶
| Scenario | Control | Why |
|---|---|---|
| CSF hazard bound must not be exceeded | Guardrail | Safety-critical — must halt immediately |
| Token budget must not be exceeded | Guardrail | Resource protection — hard limit |
| Track F1 score during training | Checkpoint | Quality monitoring — log but don't halt |
| Monitor grounding confidence | Checkpoint | Informational — flag low-quality claims |
| Human approval before production deploy | Breakpoint | High-stakes — requires human judgment |
| Clinician review before surgical plan | Breakpoint | Safety-critical — human gate required |
| No condition needed — always pause | Breakpoint with always_pause | Unconditional HITL |
For extension developers¶
If you are building your own component with the extension SDK (the g6ext.* namespace; see Custom Component), the same CSF primitives are available in code so your component can verify its own actions. The csf_guarded decorator wraps a function so it only runs when the modeled hazard stays under epsilon:
# Inside a g6ext.* extension component — import path per the extension SDK reference
@csf_guarded(hazards=["llm_call", "external_api"])
def research_with_web_search(query: str) -> str:
"""Combined hazard 0.13 < 0.20 (epsilon) -> runs.
If the combined hazard exceeded epsilon, the call is blocked instead."""
...
See the Custom Component tutorial for how to build and register an extension.
Next steps¶
- Research Pipeline — build a full research pipeline
- Custom Component — create your own CSF-aware extension component
- Security Architecture — deep dive into the CSF framework