paybondpaybond
Sign in

Recipe · Framework

Spend controls for Microsoft Agent Framework tools

spend verify via MAF function middleware before tools run, auto-evidence after success, and policy budgets for Microsoft Agent Framework — Python.

  1. 1Wire
  2. 2Authorize
  3. 3Smoke

You'll build

Microsoft Agent Framework tools with Harbor spend boundaries

Microsoft Agent Framework agents invoke tools through a function middleware pipeline. Paybond hooks that boundary — spend verify before side-effecting tools execute, then auto-evidence after success. Model inference stays on your Foundry or other chat client.

Python only — install paybond-kit[microsoft-agent-framework] for the native adapter (depends on agent-framework-core).

Adapter reference: /docs/kit/microsoft-agent-framework.

  • spend verify in function middleware

    MAF function middleware authorizes operation and amount before call_next runs the tool.

  • Auto-evidence

    Successful side-effecting calls finalize spend and submit signed evidence.

  • Policy budgets

    Versioned YAML caps per-call and intent spend for Azure / Foundry agents.

  • Python native

    Install paybond-kit[microsoft-agent-framework] — TypeScript stacks use agent-agnostic or another adapter.

Why Paybond (not just MAF tool approval)?

MAF @tool(approval_mode=...) and host HITL do not enforce a spend limit, a per-operation permission check (capability token), or a signed completion receipt tied to a spend agreement (intent). With approval_mode="never_require", Paybond middleware is the sole spend authority — do not compose MAF always_require with Paybond holds in the same sample.

Microsoft Agent Framework tool approval alone versus Paybond Harbor spend controls
  • Model / input guardrails

    MAF tool approval alone
    Yes — SDK or host checks and approvals
    With Paybond
    Yes — plus Harbor authorize at the tool boundary
  • Spend boundary

    MAF tool approval alone
    No per-tool Harbor budget or capability token
    With Paybond
    Per-call and intent budgets enforced before invoke
  • Signed evidence

    MAF tool approval alone
    SDK traces / logs only
    With Paybond
    Signed completion digests bound to the intent
  • Intent binding

    MAF tool approval alone
    No Harbor intent or settlement receipt
    With Paybond
    Capability token + intentId from authenticated bind
  • Paid tool deny / HITL

    MAF tool approval alone
    Host or SDK approvals only
    With Paybond
    spend verify, deny, or HITL hold before side effects

How it works

Paybond function middleware gates MAF tools: Harbor authorize before call_next, then auto-evidence after success.

Adapter flow

  1. Function invoke

    MAF agent invokes a side-effecting tool

  2. Paybond middleware

    Harbor authorize before call_next

    • Verify spend and operation
    • Deny or HITL hold
    • Issue / check capability
  3. Tool runs

    call_next executes your tool body

  4. Evidence

    Middleware finalizes spend + auto-evidence

Paybond function middleware gates MAF tools: Harbor authorize before call_next, then auto-evidence after success.

3-minute quickstart

Smoke the microsoft-agent-framework adapter sandbox contract:

Terminal
Terminal commandSwipe to inspect long lines
paybond login
paybond agent demo microsoft-agent-framework smoke \
  --operation paid-tool \
  --requested-spend-cents 100 \
  --evidence-preset cost_and_completion \
  --format table

Install the extra first:

Terminal
Terminal commandSwipe to inspect long lines
pip install "paybond-kit[microsoft-agent-framework]"

When the smoke succeeds you should see:

  • ✓ Spend approved
  • ✓ Tool completed
  • ✓ Evidence verified (cost_and_completion)

What success looks like

Example status after a Paybond-guarded Microsoft Agent Framework tool call: approved spend, requested amount, and verified cost_and_completion evidence.

What success looks like

Authorized tool call · illustrative

Sandbox path
Operation
paid-tool
Status
Approved
Requested
$1.00
Evidence
Verified
Preset
cost_and_completion

Scaffold

Terminal
Terminal commandSwipe to inspect long lines
paybond init agent-middleware --framework microsoft-agent-framework --out paybond_microsoft_agent_framework.py
paybond policy init --preset saas --out paybond.policy.yaml

Or the vertical template:

Terminal
Terminal commandSwipe to inspect long lines
paybond init --template microsoft-agent-framework-procurement-agent

Clone-and-run GitHub starter:

Terminal
Terminal commandSwipe to inspect long lines
git clone https://github.com/nonameuserd/paybond-microsoft-agent-framework-procurement-agent.git

Wire middleware

Recommended wiring

Bind a run with a catalog-backed spend resolver, then attach function middleware on the MAF Agent.

paybond_session.py

PY
Python code sampleSwipe to inspect long lines
from agent_framework import Agent, tool
from paybond_kit import Paybond
from paybond_kit.agent.registry import create_paybond_tool_registry
from paybond_kit.microsoft_agent_framework import (
    create_paybond_microsoft_agent_framework_config,
)

# Price lives in your catalog — not in an LLM-invented amount_cents.
FARES = {"SFO-SEA": 18_900}

@tool(name="book_flight", approval_mode="never_require")
def book_flight(route: str, seats: int = 1) -> dict:
    """Book a flight. Fare comes from the fare table, not the model."""
    cost_cents = FARES[route] * seats
    return {"status": "completed", "route": route, "cost_cents": cost_cents}

paybond = await Paybond.open(api_key=os.environ["PAYBOND_API_KEY"])
run = await paybond.agent_run.bind(
    {
        "bootstrap": {
            "kind": "sandbox",
            "operation": "book_flight",
            "requested_spend_cents": 18_900,
            "completion_preset": "cost_and_completion",
        },
        "registry": create_paybond_tool_registry(
            {
                "default_deny": True,
                "side_effecting": {
                    "book_flight": {
                        "operation": "book_flight",
                        "evidence_preset": "cost_and_completion",
                        "spend_cents": lambda args: FARES[args["route"]]
                        * int(args.get("seats", 1)),
                    }
                },
            }
        ),
    }
)
maf = create_paybond_microsoft_agent_framework_config(run, [book_flight])

agent = Agent(
    client=...,
    tools=maf.tools,
    middleware=maf.middleware,
)

Manual hook wiring

When you already bound a PaybondAgentRun:

paybond_session.py

PY
Python code sampleSwipe to inspect long lines
from paybond_kit.microsoft_agent_framework import (
    create_paybond_microsoft_agent_framework_config,
)

config = create_paybond_microsoft_agent_framework_config(run, tools)
# Agent(..., tools=config.tools, middleware=config.middleware)

Deny / hold: middleware sets context.result to a Paybond message and does not call call_next() — the model sees a tool result without stopping the function-calling loop.

Bypass classes: direct tool invocation bypassing the agent, host plugins outside FunctionInvokingChatClient, and any non-middleware path are unguarded unless separately wrapped.

Production checklist

Production checklist for Paybond-guarded Microsoft Agent Framework tools.

Production checklist

Works with

Works with

  • Microsoft Agent Framework
  • OpenAI
  • MCP
  • Agent-agnostic

Ready to test?

Public template: paybond-microsoft-agent-framework-procurement-agent.