Paybond integrates with Microsoft Agent Framework at the function middleware boundary — Harbor verify runs before side-effecting tools execute, then auto-evidence fires after success. Model inference stays on your Foundry / OpenAI / other chat client; Paybond guards paid and side-effecting tool calls only.
Python only (v1) — TypeScript Kit does not ship a MAF adapter; use agent-agnostic or MCP for other hosts. No separate AutoGen or Semantic Kernel packages — MAF is the Microsoft enterprise path.
Install
Install
npm install @paybond/kitImport from @paybond/kit/agent
// Microsoft Agent Framework is Python-only — use paybond-kit[microsoft-agent-framework] in Python projects.- Python only. TypeScript Kit does not ship a Microsoft Agent Framework adapter — use agent-agnostic middleware or MCP for other hosts.
- Python: `paybond agent demo microsoft-agent-framework smoke` requires the optional `microsoft-agent-framework` extra (`agent-framework-core`). Use `pip install "paybond-kit[microsoft-agent-framework]"`, `pipx install 'paybond-kit[microsoft-agent-framework]'`, or `pipx inject paybond-kit agent-framework-core` (when base paybond-kit is already installed).
- Smoke: `paybond agent demo microsoft-agent-framework smoke --operation paid-tool --requested-spend-cents 100 --evidence-preset cost_and_completion --format json`.
- Attach `middleware` on the Agent — tools-only wrap is insufficient for this framework.
Recommended wiring
One-liner (sandbox): paybond.instrument({ policy, framework: "microsoft-agent-framework", tools }) returns passthrough tools plus required function middleware on result.hooks.middleware (or result.hooks.microsoft_agent_framework_config.middleware). Production: omit sandbox and call instrumented.bind() per session.
from agent_framework import Agent, tool from paybond_kit import Paybond # Paybond middleware is the sole spend authority in this sample. @tool(approval_mode="never_require") def submit_po(amount_cents: int) -> str: ... paybond = await Paybond.open(api_key=os.environ["PAYBOND_API_KEY"]) result = await paybond.instrument( policy="./paybond.policy.yaml", framework="microsoft-agent-framework", tools=[submit_po], ) agent = Agent( client=..., # FoundryChatClient or any FunctionInvoking client tools=result.tools, middleware=result.hooks.middleware, )
Already bound a run? Use create_paybond_microsoft_agent_framework_config(run, tools) — returns { tools, middleware, wrap_tool }. Middleware-only: create_paybond_microsoft_agent_framework_middleware(run).
Important: tools-only wrap is insufficient for MAF. You must attach middleware on the agent (same class of footgun as LangGraph without awrap_tool_call).
See Agent middleware for run binding, registry rules, and tenant isolation.
Dual approval warning
With @tool(approval_mode="never_require"), Paybond middleware is the sole spend authority. Do not compose MAF always_require HITL with Paybond approval holds in the same sample — pick one approval path.
Deny / hold UX
On PaybondSpendDeniedError / PaybondSpendApprovalRequiredError, middleware sets context.result to a clear string and does not call call_next(). The model sees a tool result; the function-calling loop continues. Do not raise MiddlewareTermination or set terminate for deny/hold (that stops the whole loop).
Scaffold and smoke
paybond init agent-middleware --framework microsoft-agent-framework --out paybond_microsoft_agent_framework.py paybond policy init --preset saas --out paybond.policy.yaml
Validate authorization and evidence without a live MAF agent or LLM:
paybond login paybond agent demo microsoft-agent-framework smoke \ --operation paid-tool \ --requested-spend-cents 100 \ --evidence-preset cost_and_completion \ --format json
Requires the optional extra: pip install "paybond-kit[microsoft-agent-framework]" (depends on agent-framework-core, not the full Foundry meta-package). With pipx: pipx install 'paybond-kit[microsoft-agent-framework]' or pipx inject paybond-kit agent-framework-core.
Known limitations (bypass class)
Paybond only governs tools that flow through the agent's function-invocation pipeline:
- Direct tool invocation that bypasses the agent is unguarded unless separately wrapped.
- Host plugins outside
FunctionInvokingChatClientare unguarded. - Any non-middleware path is unguarded.
Harbor owns authorize claim, deny-before-side-effect, and post-exec evidence via wrap_execute — the adapter does not reimplement those semantics.
Related
- Agent middleware — run binding, registry, auto-evidence
- Agent-agnostic adapter — fallback for custom orchestrators
- Support matrix — shipped framework surfaces
- Microsoft Agent Framework spend controls guide — task-oriented wiring walkthrough