Skip to main content

ForceEquals SDK — builder integration guide

How to govern your coded agent with ForceEquals. Share this with customers and internal agent authors.

You write the agent. ForceEquals decides whether each step may continue, must pause for a human, or must be blocked.

Your agent reports facts  →  ForceEquals applies org policy  →  Your agent obeys

You do not write pause/poll/resume loops. That lives in the SDK.

You do not run or deploy a ForceEquals server. Install the SDK; ForceEquals hosts the API and Momentum.


1. What you install vs what ForceEquals hosts

Piece Who runs it What it is
SDK (pip install forceequals) You, inside your agent process Small Python library
ForceEquals API ForceEquals (hosted) Policy + approvals
Momentum ForceEquals web app Create API key, policies, approve cards

The SDK is not a server. You do not deploy it. You install it. ForceEquals deploys the API and Momentum.


2. What you need (credentials)

Create these in Momentum while logged in (your email owns the key).

Item Example Where
API key fe_live_... Momentum → API Key → Generate. Shown once.
Agent id github-agent Momentum → Add Agent / Connect. Must match FORCEEQUALS_AGENT_ID.

Put them in your agent .env (never commit the key):

FORCEEQUALS_API_KEY=fe_live_your_key_here
FORCEEQUALS_AGENT_ID=github-agent

The SDK calls the hosted ForceEquals API at https://forceequals-momentum-api.onrender.com/. You do not set FORCEEQUALS_BASE_URL. That URL is built into the SDK.

You do not send your email in the SDK. The API key is your identity. The API looks up the key and knows which Momentum user owns it.

Not ForceEquals credentials (those stay yours):

  • GitHub token, OpenAI/Claude key, database passwords — your agent’s own tools.

If the key is missing, revoked, or not created under your Momentum login, SDK calls return 401.


3. Install

pip install forceequals

Until the package is on PyPI, from this repo:

cd forceequals-platform
pip install -e .

That installs only the forceequals package (the SDK). You do not install or start anything from an API folder.

Python 3.10+.


4. Integrate — step by step

Step 1 — Create the client once

from forceequals import (
    ForceEquals,
    GovernanceBlockedError,
    GovernanceRejectedError,
)

fe = ForceEquals()  # reads FORCEEQUALS_API_KEY + FORCEEQUALS_AGENT_ID

Step 2 — Wrap each business run with @fe.governed

One GitHub PR, one loan application, one user message = one run.

class MyAgent:
    @fe.governed
    def handle_event(self, payload: dict) -> None:
        ...

This allocates execution_id / case_id. Without it, emit_event fails.

Keep your process alive yourself (a while True or worker). ForceEquals only governs this run.

Step 3 — Report facts with emit_event

Call this after something meaningful happened. ForceEquals policies decide continue / pause / block.

decision = fe.emit_event(
    "pull_request.opened",
    {
        "repo": payload["repo"],
        "pr": payload["number"],
        "title": payload["title"],
        "base_branch": payload["base_branch"],
    },
)
# If this returns, status was continue (or pause was approved).
# If policy blocked, GovernanceBlockedError is raised.

Do not check policy yourself. Send facts only.

Step 4 — Explicit human gate with request_approval

Use this when you already know a human must approve (merge to main, pay out money). Always pauses.

fe.request_approval(
    title=f"Merge PR #{payload['number']} into {payload['base_branch']}",
    context={"pr": payload["number"], "repo": payload["repo"]},
)

The SDK waits until a reviewer approves, denies, or requests changes in Momentum.

Step 5 — Catch block / reject so the process stays up

def run_one(agent, payload):
    try:
        agent.handle_event(payload)
    except GovernanceBlockedError as exc:
        print(f"Blocked by policy: {exc}")
    except GovernanceRejectedError as exc:
        print(f"Rejected by reviewer: {exc}")

Blocked/rejected stops this run, not the agent process.

Step 6 — Keep doing your work

LLM review, GitHub API, tools — that is your code. After a successful request_approval, continue (comment, merge, notify). ForceEquals does not merge GitHub for you.


5. Minimal example

from forceequals import ForceEquals, GovernanceBlockedError, GovernanceRejectedError

fe = ForceEquals()

class GitHubAgent:
    @fe.governed
    def handle_pull_request(self, pr: dict) -> None:
        fe.emit_event("pull_request.opened", {
            "repo": pr["repo"],
            "pr": pr["number"],
            "title": pr["title"],
        })
        # your review / tools here
        fe.request_approval(
            title=f"Merge PR #{pr['number']}",
            context={"pr": pr["number"]},
        )
        print("Governance allowed this merge (you still perform it).")

agent = GitHubAgent()
try:
    agent.handle_pull_request({"repo": "acme/app", "number": 42, "title": "Fix"})
except GovernanceBlockedError as exc:
    print("Blocked:", exc)
except GovernanceRejectedError as exc:
    print("Rejected:", exc)

6. What ForceEquals returns

Status Meaning What the SDK does
continue Allowed Returns; your next line runs
paused Human needed Waits; card appears in Momentum
blocked Hard no Raises GovernanceBlockedError

request_approval always pauses. emit_event is adaptive (policies + Policy LLM).

Optional: a policy may return override_result (forced answer/tool output). The SDK applies that; you do not.


7. Try it

  1. Log into Momentum → create an API key → copy fe_live_... (shown once).
  2. Add / connect an agent. Copy the agent id. It must match FORCEEQUALS_AGENT_ID.
  3. pip install forceequals (or pip install -e . from forceequals-platform/ until PyPI is live).
  4. Put the two env vars in your agent .env. Do not set an API URL (it defaults to https://forceequals-momentum-api.onrender.com/).
  5. Run your agent. On pause, open Momentum → Feed and Approve, Deny, or Request Changes.

The agent talks to https://forceequals-momentum-api.onrender.com/. You never start a local ForceEquals server.


8. Checklist

  • Momentum account and API key (fe_live_...)
  • FORCEEQUALS_AGENT_ID matches the agent registered in Momentum
  • pip install forceequals
  • ForceEquals() once at process start
  • @fe.governed on each run
  • emit_event after real work facts
  • request_approval on irreversible steps
  • Catch GovernanceBlockedError / GovernanceRejectedError
  • Your own loop keeps the agent online for the next event

9. Related

Doc Audience
PUBLISH_AND_DEPLOY.md ForceEquals team — PyPI + API hosting
FLOW_GUIDE.md Internal product flow
NO_CODE_INTEGRATION.md n8n / Agentforce (HTTP, no Python SDK)

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

forceequals-0.1.1.tar.gz (18.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

forceequals-0.1.1-py3-none-any.whl (17.7 kB view details)

Uploaded Python 3

File details

Details for the file forceequals-0.1.1.tar.gz.

File metadata

  • Download URL: forceequals-0.1.1.tar.gz
  • Upload date:
  • Size: 18.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.14

File hashes

Hashes for forceequals-0.1.1.tar.gz
Algorithm Hash digest
SHA256 78bb484412c1300e59c938cc32297bb8e8f508c15cb41decab96020467dc5c6c
MD5 fe5cdaeead5cfae0fa6838364a85fae9
BLAKE2b-256 abc2698488333120a358d28c9ec7376598d2378181c87f1c53082cad1993b29c

See more details on using hashes here.

File details

Details for the file forceequals-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: forceequals-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 17.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.14

File hashes

Hashes for forceequals-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 ad22590d65ce2b9e75de09ca5b29703a0fd8d61a58f7708e3e14714f3e919ad7
MD5 209a50fd85b8522ca5081cb4526e2ada
BLAKE2b-256 329fc2b10521b2dce83e775b9dcad1d7d5d1528b3fce673566e808a0d2fa0fc5

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page