Govern Your Own Tool

Step-by-step guide to wrapping custom tools and functions with Faramesh governance.

The Pattern

  1. Submit the action to Faramesh before execution

  2. Check the status (allow, deny, or pending approval)

  3. Execute only if allowed or approved

  4. Report the result back to Faramesh

Example: Refund Function

from faramesh.sdk.client import ExecutionGovernorClient

client = ExecutionGovernorClient()  # Uses FARAMESH_URL and FARAMESH_API_KEY

def refund_customer(amount: float, customer_id: str) -> dict:
    # 1. Submit to Faramesh
    action = client.submit_action(
        tool="refund",
        operation="process",
        params={"amount": amount, "customer_id": customer_id},
        context={"agent_id": "billing-bot"}
    )

    # 2. Check status
    if action["status"] == "denied":
        raise PermissionError(f"Refund denied: {action.get('reason')}")

    if action["status"] == "pending_approval":
        print(f"Refund needs approval. Action ID: {action['id']}")
        print("Open the dashboard to approve or deny.")
        # Option: poll until approved, or exit and let user approve
        import time
        for _ in range(150):  # 5 minutes
            time.sleep(2)
            updated = client.get_action(action["id"])
            if updated["status"] in ("approved", "allowed"):
                break
            if updated["status"] == "denied":
                raise PermissionError("Refund was denied")
        else:
            raise TimeoutError("Approval timeout")

    # 3. Execute only if allowed
    if action["status"] not in ("allowed", "approved"):
        raise PermissionError(f"Refund not approved. Status: {action['status']}")

    # 4. Do the actual refund
    try:
        result = your_refund_logic(amount, customer_id)
        client.report_result(action["id"], success=True, result=result)
        return result
    except Exception as e:
        client.report_result(action["id"], success=False, error=str(e))
        raise
from faramesh.sdk.client import ExecutionGovernorClient

client = ExecutionGovernorClient()  # Uses FARAMESH_URL and FARAMESH_API_KEY

def refund_customer(amount: float, customer_id: str) -> dict:
    # 1. Submit to Faramesh
    action = client.submit_action(
        tool="refund",
        operation="process",
        params={"amount": amount, "customer_id": customer_id},
        context={"agent_id": "billing-bot"}
    )

    # 2. Check status
    if action["status"] == "denied":
        raise PermissionError(f"Refund denied: {action.get('reason')}")

    if action["status"] == "pending_approval":
        print(f"Refund needs approval. Action ID: {action['id']}")
        print("Open the dashboard to approve or deny.")
        # Option: poll until approved, or exit and let user approve
        import time
        for _ in range(150):  # 5 minutes
            time.sleep(2)
            updated = client.get_action(action["id"])
            if updated["status"] in ("approved", "allowed"):
                break
            if updated["status"] == "denied":
                raise PermissionError("Refund was denied")
        else:
            raise TimeoutError("Approval timeout")

    # 3. Execute only if allowed
    if action["status"] not in ("allowed", "approved"):
        raise PermissionError(f"Refund not approved. Status: {action['status']}")

    # 4. Do the actual refund
    try:
        result = your_refund_logic(amount, customer_id)
        client.report_result(action["id"], success=True, result=result)
        return result
    except Exception as e:
        client.report_result(action["id"], success=False, error=str(e))
        raise
from faramesh.sdk.client import ExecutionGovernorClient

client = ExecutionGovernorClient()  # Uses FARAMESH_URL and FARAMESH_API_KEY

def refund_customer(amount: float, customer_id: str) -> dict:
    # 1. Submit to Faramesh
    action = client.submit_action(
        tool="refund",
        operation="process",
        params={"amount": amount, "customer_id": customer_id},
        context={"agent_id": "billing-bot"}
    )

    # 2. Check status
    if action["status"] == "denied":
        raise PermissionError(f"Refund denied: {action.get('reason')}")

    if action["status"] == "pending_approval":
        print(f"Refund needs approval. Action ID: {action['id']}")
        print("Open the dashboard to approve or deny.")
        # Option: poll until approved, or exit and let user approve
        import time
        for _ in range(150):  # 5 minutes
            time.sleep(2)
            updated = client.get_action(action["id"])
            if updated["status"] in ("approved", "allowed"):
                break
            if updated["status"] == "denied":
                raise PermissionError("Refund was denied")
        else:
            raise TimeoutError("Approval timeout")

    # 3. Execute only if allowed
    if action["status"] not in ("allowed", "approved"):
        raise PermissionError(f"Refund not approved. Status: {action['status']}")

    # 4. Do the actual refund
    try:
        result = your_refund_logic(amount, customer_id)
        client.report_result(action["id"], success=True, result=result)
        return result
    except Exception as e:
        client.report_result(action["id"], success=False, error=str(e))
        raise

Example: Delete User

def delete_user(user_id: str) -> bool:
    action = client.submit_action(
        tool="user_management",
        operation="delete",
        params={"user_id": user_id},
        context={"agent_id": "admin-bot"}
    )

    if action["status"] == "denied":
        raise PermissionError(f"Delete denied: {action.get('reason')}")

    if action["status"] == "pending_approval":
        print(f"Delete needs approval: {action['id']}")
        # Same polling logic as above...

    # Execute deletion
    try:
        your_delete_logic(user_id)
        client.report_result(action["id"], success=True)
        return True
    except Exception as e:
        client.report_result(action["id"], success=False, error=str(e))
        raise
def delete_user(user_id: str) -> bool:
    action = client.submit_action(
        tool="user_management",
        operation="delete",
        params={"user_id": user_id},
        context={"agent_id": "admin-bot"}
    )

    if action["status"] == "denied":
        raise PermissionError(f"Delete denied: {action.get('reason')}")

    if action["status"] == "pending_approval":
        print(f"Delete needs approval: {action['id']}")
        # Same polling logic as above...

    # Execute deletion
    try:
        your_delete_logic(user_id)
        client.report_result(action["id"], success=True)
        return True
    except Exception as e:
        client.report_result(action["id"], success=False, error=str(e))
        raise
def delete_user(user_id: str) -> bool:
    action = client.submit_action(
        tool="user_management",
        operation="delete",
        params={"user_id": user_id},
        context={"agent_id": "admin-bot"}
    )

    if action["status"] == "denied":
        raise PermissionError(f"Delete denied: {action.get('reason')}")

    if action["status"] == "pending_approval":
        print(f"Delete needs approval: {action['id']}")
        # Same polling logic as above...

    # Execute deletion
    try:
        your_delete_logic(user_id)
        client.report_result(action["id"], success=True)
        return True
    except Exception as e:
        client.report_result(action["id"], success=False, error=str(e))
        raise

Policy for Your Tool

Add a rule for your custom tool:

rules:
  - match:
      tool: "refund"
      operation: "process"
      amount_gt: 100
    require_approval: true
    reason: "Large refunds need approval"
    risk: high

  - match:
      tool: "refund"
      operation: "process"
      amount_lte: 100
    allow: true
    reason: "Small refunds allowed"
    risk

rules:
  - match:
      tool: "refund"
      operation: "process"
      amount_gt: 100
    require_approval: true
    reason: "Large refunds need approval"
    risk: high

  - match:
      tool: "refund"
      operation: "process"
      amount_lte: 100
    allow: true
    reason: "Small refunds allowed"
    risk

rules:
  - match:
      tool: "refund"
      operation: "process"
      amount_gt: 100
    require_approval: true
    reason: "Large refunds need approval"
    risk: high

  - match:
      tool: "refund"
      operation: "process"
      amount_lte: 100
    allow: true
    reason: "Small refunds allowed"
    risk

Without the SDK (cURL)

# Submit
ACTION=$(curl -X POST $FARAMESH_URL/v1/actions \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"tool":"refund","operation":"process","params":{"amount":150},"context":{"agent_id":"billing-bot"}}')

# Check status, approve if needed, then report result
curl -X POST $FARAMESH_URL/v1/actions/$ACTION_ID/result \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"success":true,"result":{...}}'
# Submit
ACTION=$(curl -X POST $FARAMESH_URL/v1/actions \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"tool":"refund","operation":"process","params":{"amount":150},"context":{"agent_id":"billing-bot"}}')

# Check status, approve if needed, then report result
curl -X POST $FARAMESH_URL/v1/actions/$ACTION_ID/result \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"success":true,"result":{...}}'
# Submit
ACTION=$(curl -X POST $FARAMESH_URL/v1/actions \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"tool":"refund","operation":"process","params":{"amount":150},"context":{"agent_id":"billing-bot"}}')

# Check status, approve if needed, then report result
curl -X POST $FARAMESH_URL/v1/actions/$ACTION_ID/result \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"success":true,"result":{...}}'

Next Steps

Was this helpful?

Was this helpful?

Was this helpful?

Previous

More

Previous

More

Previous

More

Next

More

Next

More

Next

More

Table of content

Table of content

Table of content

Govern Your Own Tool

Govern Your Own Tool