Skip to content

feat(types): add Fiduciary Circuit Breaker risk extension#164

Closed
ravyg wants to merge 3 commits intogoogle-agentic-commerce:mainfrom
ravyg:fcb-governance
Closed

feat(types): add Fiduciary Circuit Breaker risk extension#164
ravyg wants to merge 3 commits intogoogle-agentic-commerce:mainfrom
ravyg:fcb-governance

Conversation

@ravyg
Copy link

@ravyg ravyg commented Feb 5, 2026

Summary

Adds structured risk signal types for AP2 Section 7.4 (Risk Signals), introducing a Fiduciary Circuit Breaker (FCB) pattern for runtime governance of autonomous agent transactions.

FCB enables standardized trip conditions, state-based controls, and human escalation to mitigate risky or anomalous behavior beyond mandate-based authorization.


Changes

  • Add Python types: src/ap2/types/risk.py
  • Add Go types: samples/go/pkg/ap2/types/risk.go
  • Add docs: docs/topics/fiduciary-circuit-breaker.md
  • Export types in src/ap2/types/__init__.py
  • Update navigation in mkdocs.yml

Features

  • Trip conditions: value, cumulative, velocity, anomaly, extensible
  • Governance state machine: CLOSED → OPEN → HALF_OPEN → TERMINATED
  • Structured risk signals for issuer/network visibility
  • Human escalation support

Tests

  • Go: 11 tests (constants, helpers, JSON, integration scenario)
  • Python: 22 tests (enums, models, round-trip, scenario)
  • Minor formatting fix in risk.go
  • Locally tested with MCP integration
    • Tested local MCP calling create_quotes with values ($450, $8000, $11250) - Confirmed FCB correctly passed low-value quotes, triggered warning at 80% threshold, and blocked quotes exceeding $10,000 with escalation ID generated.

Compatibility

Additive only — no breaking changes.

Fixes #163

@ravyg ravyg requested a review from a team as a code owner February 5, 2026 01:39
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @ravyg, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request integrates the Fiduciary Circuit Breaker (FCB) into the Agent Payments Protocol (AP2), enhancing the protocol's ability to monitor and govern autonomous agent behavior in real-time. By introducing structured risk types and a state-based control mechanism, the FCB allows for dynamic assessment of transaction risks, enabling automated intervention or human escalation when predefined conditions are met. This ensures agents operate within acceptable risk parameters, providing greater security and trust in automated financial transactions.

Highlights

  • Fiduciary Circuit Breaker (FCB) Extension: Introduces the Fiduciary Circuit Breaker (FCB) extension for AP2, providing structured risk signal types for Section 7.4 (Risk Signals).
  • Runtime Governance for Autonomous Agents: Enables runtime governance for autonomous agent transactions, complementing mandate-based authorization by monitoring how agents exercise their authority in real-time.
  • FCB State Machine and Trip Conditions: Defines a state machine for FCB (CLOSED, OPEN, HALF_OPEN, TERMINATED) and various trip conditions (e.g., VALUE_THRESHOLD, CUMULATIVE_THRESHOLD, ANOMALY) to detect risky behavior.
  • Python and Go Type Definitions: Adds comprehensive Python and Go type definitions for the FCB risk payload, facilitating integration into AP2 messages and ensuring type safety.
  • New Documentation: Includes new documentation explaining the FCB conceptual model, states, trip conditions, usage in AP2 messages, and benefits for the payment ecosystem.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • docs/topics/fiduciary-circuit-breaker.md
    • New documentation detailing the FCB extension, its conceptual model, states, trip conditions, and integration with AP2 messages.
  • mkdocs.yml
    • Updated navigation configuration to include the new FCB documentation page.
  • samples/go/pkg/ap2/types/risk.go
    • Added Go data structures and enums for TripConditionType, TripConditionStatus, FCBState, AgentModality, EscalationDecision, TripConditionResult, HumanEscalation, FCBEvaluation, and RiskPayload.
  • samples/go/pkg/ap2/types/risk_test.go
    • Introduced unit tests for the Go FCB types, covering enum values, struct constructors, AddTripResult, HasTripped, and JSON serialization.
  • src/ap2/types/init.py
    • Modified to export the newly added Python FCB risk types.
  • src/ap2/types/risk.py
    • Added Python Pydantic models and Enums for the FCB risk extension, including TripConditionType, TripConditionStatus, FCBState, AgentModality, EscalationDecision, TripConditionResult, HumanEscalation, FCBEvaluation, and RiskPayload.
  • tests/test_risk.py
    • Added Python unit and integration tests for the FCB Pydantic models, covering enum definitions, model instantiation, JSON serialization, and a complete scenario.
Activity
  • New feature: Implemented the Fiduciary Circuit Breaker (FCB) risk extension.
  • Issue resolution: Addresses and fixes issue [Feat]: Define structured Risk Payload schema for Section 7.4 Risk Signals #163.
  • Test coverage: Added 11 Go tests and 22 Python tests to validate the new FCB types and logic.
  • Local validation: Verified FCB functionality through local MCP integration testing, confirming correct handling of various transaction values (passing, warning, blocking).
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a significant and well-designed Fiduciary Circuit Breaker (FCB) extension for risk management. The changes include new data types for Python and Go, comprehensive documentation, and thorough test suites. The code quality is high, with excellent use of language features like pydantic in Python and idiomatic patterns in Go. My review includes a few minor suggestions to further improve the clarity of the documentation and enhance test coverage for edge cases.

Comment on lines 237 to 258
```go
import "github.com/google-agentic-commerce/ap2/samples/go/pkg/ap2/types"

// Create an FCB evaluation
evaluation := types.NewFCBEvaluation(types.FCBStateClosed)
evaluation.AddTripResult(types.TripConditionResult{
ConditionType: types.TripConditionValueThreshold,
Status: types.TripConditionStatusPass,
Threshold: floatPtr(100000),
ActualValue: floatPtr(45000),
})
evaluation.RiskScore = floatPtr(0.15)

// Create risk payload
riskPayload := types.NewRiskPayload(types.AgentModalityHumanNotPresent)
riskPayload.FCBEvaluation = evaluation
riskPayload.AgentID = stringPtr("agent_xyz")
```
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The Go code example uses helper functions floatPtr and stringPtr which are not defined in the standard library or within this project's provided code. This could be confusing for users trying to run the example. For better clarity and to make the example self-contained, I suggest showing how to create pointers explicitly, similar to the pattern used in the Go test files.

Suggested change
```go
import "github.com/google-agentic-commerce/ap2/samples/go/pkg/ap2/types"
// Create an FCB evaluation
evaluation := types.NewFCBEvaluation(types.FCBStateClosed)
evaluation.AddTripResult(types.TripConditionResult{
ConditionType: types.TripConditionValueThreshold,
Status: types.TripConditionStatusPass,
Threshold: floatPtr(100000),
ActualValue: floatPtr(45000),
})
evaluation.RiskScore = floatPtr(0.15)
// Create risk payload
riskPayload := types.NewRiskPayload(types.AgentModalityHumanNotPresent)
riskPayload.FCBEvaluation = evaluation
riskPayload.AgentID = stringPtr("agent_xyz")
```
import "github.com/google-agentic-commerce/ap2/samples/go/pkg/ap2/types"
// Create an FCB evaluation
evaluation := types.NewFCBEvaluation(types.FCBStateClosed)
threshold := 100000.0
actualValue := 45000.0
riskScore := 0.15
evaluation.AddTripResult(types.TripConditionResult{
ConditionType: types.TripConditionValueThreshold,
Status: types.TripConditionStatusPass,
Threshold: &threshold,
ActualValue: &actualValue,
})
evaluation.RiskScore = &riskScore
// Create risk payload
riskPayload := types.NewRiskPayload(types.AgentModalityHumanNotPresent)
riskPayload.FCBEvaluation = evaluation
agentID := "agent_xyz"
riskPayload.AgentID = &agentID

Comment on lines 60 to 65
| State | Behavior | Entry Condition |
|-------|----------|-----------------|
| **CLOSED** | Normal operation. Agent acts autonomously. | Initial state; or human approves |
| **OPEN** | All actions blocked. Requires human review. | Any trip condition fails |
| **HALF_OPEN** | Limited operations with enhanced monitoring. | Human approves with conditions |
| **TERMINATED** | Permanently halted. No recovery. | Human rejects; or timeout |
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

low

The state transition diagram on lines 69-85 provides more detail on state transitions than this table of FCB states. To improve clarity and consistency, consider updating the "Entry Condition" column to reflect all possible transitions shown in the diagram. For example:

  • The entry condition for CLOSED could also include transitioning from HALF_OPEN when "conditions are met".
  • The entry condition for OPEN could also include transitioning from HALF_OPEN when "conditions are violated".

Comment on lines 210 to 238
def test_risk_score_bounds(self):
"""Test risk_score validation."""
# Valid score
eval = FCBEvaluation(
fcb_state=FCBState.CLOSED,
trips_evaluated=1,
trips_triggered=0,
risk_score=0.5,
)
assert eval.risk_score == 0.5

# Score at boundaries
eval_min = FCBEvaluation(
fcb_state=FCBState.CLOSED,
trips_evaluated=1,
trips_triggered=0,
risk_score=0.0,
)
assert eval_min.risk_score == 0.0

eval_max = FCBEvaluation(
fcb_state=FCBState.CLOSED,
trips_evaluated=1,
trips_triggered=0,
risk_score=1.0,
)
assert eval_max.risk_score == 1.0
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

low

The test_risk_score_bounds test currently only verifies valid risk_score values. To make the test more robust, I suggest adding cases to verify that pydantic.ValidationError is raised for out-of-bounds values (e.g., < 0.0 or > 1.0), ensuring the validation constraints are enforced correctly.

    def test_risk_score_bounds(self):
        """Test risk_score validation."""
        from pydantic import ValidationError

        # Valid score
        eval = FCBEvaluation(
            fcb_state=FCBState.CLOSED,
            trips_evaluated=1,
            trips_triggered=0,
            risk_score=0.5,
        )
        assert eval.risk_score == 0.5

        # Score at boundaries
        eval_min = FCBEvaluation(
            fcb_state=FCBState.CLOSED,
            trips_evaluated=1,
            trips_triggered=0,
            risk_score=0.0,
        )
        assert eval_min.risk_score == 0.0

        eval_max = FCBEvaluation(
            fcb_state=FCBState.CLOSED,
            trips_evaluated=1,
            trips_triggered=0,
            risk_score=1.0,
        )
        assert eval_max.risk_score == 1.0

        # Invalid scores
        with pytest.raises(ValidationError):
            FCBEvaluation(
                fcb_state=FCBState.CLOSED,
                trips_evaluated=1,
                trips_triggered=0,
                risk_score=-0.1,
            )

        with pytest.raises(ValidationError):
            FCBEvaluation(
                fcb_state=FCBState.CLOSED,
                trips_evaluated=1,
                trips_triggered=0,
                risk_score=1.1,
            )

@ravyg ravyg force-pushed the fcb-governance branch 2 times, most recently from 8fc10ee to d3686b5 Compare February 5, 2026 02:46
This PR implements structured risk types for AP2 Section 7.4 (Risk Signals),
which was "intentionally left open-ended" in the v0.1 specification.

The Fiduciary Circuit Breaker (FCB) pattern provides runtime governance for
autonomous agent transactions through:

- Trip conditions that evaluate agent behavior against predefined thresholds
  (VALUE_THRESHOLD, CUMULATIVE_THRESHOLD, VELOCITY, ANOMALY, etc.)
- A state machine for governance (CLOSED → OPEN → HALF_OPEN → TERMINATED)
- Human escalation protocol for exceptional cases
- Structured risk signals for network/issuer visibility

Changes:
- Add src/ap2/types/risk.py with Python type definitions
- Add samples/go/pkg/ap2/types/risk.go with Go type definitions
- Add docs/topics/fiduciary-circuit-breaker.md with documentation
- Update src/ap2/types/__init__.py to export new types
- Update mkdocs.yml to include FCB in navigation

This addresses the gap identified in Section 7.4 where temporal gaps,
user asynchronicity, and agent identity verification require runtime
governance beyond what mandate-based authorization provides.>

test: Add unit tests for FCB risk types

Add comprehensive unit tests for the Fiduciary Circuit Breaker (FCB)
risk extension types:

Go tests (samples/go/pkg/ap2/types/risk_test.go):
- 11 tests covering type constants, helper methods, JSON serialization
- Tests for NewHumanEscalation, NewFCBEvaluation, AddTripResult
- Complete integration scenario test

Python tests (tests/test_risk.py):
- 22 tests covering all enum types and Pydantic models
- JSON round-trip serialization tests
- B2B quote negotiation integration scenario

Also includes minor formatting fix to risk.go (whitespace alignment).

chore: add gitleaks config to allowlist AP2 data key constants

The data key constants like 'ap2.risk.FCBEvaluation' are namespace
identifiers, not secrets. This config prevents false positive alerts.
@ravyg ravyg closed this Feb 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feat]: Define structured Risk Payload schema for Section 7.4 Risk Signals

1 participant