Microsoft Agent Framework agents invoke tools through a function middleware pipeline. Paybond hooks that boundary — Harbor 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.
Harbor 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 Harbor spend budgets, capability tokens, or signed completion evidence bound to an 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.
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
- Harbor verify, deny, or HITL hold before side effects
| Capability | MAF tool approval alone | With Paybond |
|---|---|---|
| Model / input guardrails | Yes — SDK or host checks and approvals | Yes — plus Harbor authorize at the tool boundary |
| Spend boundary | No per-tool Harbor budget or capability token | Per-call and intent budgets enforced before invoke |
| Signed evidence | SDK traces / logs only | Signed completion digests bound to the intent |
| Intent binding | No Harbor intent or settlement receipt | Capability token + intentId from authenticated bind |
| Paid tool deny / HITL | Host or SDK approvals only | Harbor verify, deny, or HITL hold before side effects |
How it works
Adapter flow
Function invoke
MAF agent invokes a side-effecting tool
Paybond middleware
Harbor authorize before call_next
- Verify spend and operation
- Deny or HITL hold
- Issue / check capability
Tool runs
call_next executes your tool body
Evidence
Middleware finalizes spend + auto-evidence
Paybond function middleware gates MAF tools: Harbor authorize before call_next, then auto-evidence after success.
Python native adapter
Install pip install "paybond-kit[microsoft-agent-framework]". Attach middleware on the Agent — tools-only wrap is insufficient. TypeScript stacks should use agent-agnostic spend controls or another framework adapter.
3-minute quickstart
Smoke the microsoft-agent-framework adapter Harbor contract:
terminal
paybond login
paybond agent demo microsoft-agent-framework smoke \
--operation paid-tool \
--requested-spend-cents 100 \
--evidence-preset cost_and_completion \
--format tableInstall the extra first:
terminal
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
What success looks like
Authorized tool call · illustrative
- Operation
- paid-tool
- Status
- Approved
- Requested
- $1.00
- Evidence
- Verified
- Preset
- cost_and_completion
Scaffold
terminal
paybond init agent-middleware --framework microsoft-agent-framework --out paybond_microsoft_agent_framework.py
paybond policy init --preset saas --out paybond.policy.yamlWire middleware
Recommended wiring
paybond.instrument with framework microsoft-agent-framework returns tools plus required function middleware for your MAF Agent.
paybond_session.py
from agent_framework import Agent, tool
from paybond_kit import Paybond
@tool(approval_mode="never_require")
def book_flight(amount_cents: int) -> dict:
"""Book a flight."""
...
paybond = await Paybond.open(api_key=os.environ["PAYBOND_API_KEY"])
result = await paybond.instrument(
policy="./paybond.policy.yaml",
framework="microsoft-agent-framework",
tools=[book_flight],
)
agent = Agent(
client=...,
tools=result.tools,
middleware=result.hooks.middleware,
)Manual hook wiring
When you already bound a PaybondAgentRun:
paybond_session.py
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
- Scaffold middleware with paybond init agent-middleware --framework microsoft-agent-framework
- Init a policy preset (e.g. saas) and validate tools
- Wire paybond.instrument(framework="microsoft-agent-framework") and attach middleware
- Bind intentId and capabilityToken per session in production
- Smoke with paybond agent demo microsoft-agent-framework smoke before ship
Works with
Works with
- Microsoft Agent Framework
- OpenAI
- MCP
- Agent-agnostic