paybondpaybond
Sign in

Microsoft Agent Framework adapter

Microsoft Agent Framework (MAF) spend controls — gate paid tools with Harbor verify via function middleware and automatic evidence.

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/kit

Import 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.

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 FunctionInvokingChatClient are 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.