Jump to content

Connect SuperML | Leeroopedia MCP: Equip your AI agents with best practices, code verification, and debugging knowledge. Powered by Leeroo — building Organizational Superintelligence. Contact us at founders@leeroo.com.

Principle:Microsoft Agent framework Declarative Tool Binding

From Leeroopedia
Revision as of 18:18, 16 February 2026 by Admin (talk | contribs) (Auto-imported from principles/Microsoft_Agent_framework_Declarative_Tool_Binding.md)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Template:Principle

Overview

Declarative Tool Binding is the pattern in the Microsoft Agent Framework for connecting plain Python functions to YAML-defined tool specifications without using the @tool decorator. Instead of decorating functions, the developer writes ordinary Python functions and maps them to YAML tool names via the AgentFactory bindings parameter. The key in the bindings dictionary must match the bindings key declared in the YAML tool definition.

This is a user-defined pattern. The framework provides the YAML loading infrastructure and the AgentFactory binding mechanism; the user supplies the Python function implementations that fulfill the tool contracts defined in YAML.

Property Value
Category Declarative Systems
Source Sample: python/samples/getting_started/declarative/get_weather_agent.py
API AgentFactory(client=client, bindings={"key": callable})
Import from agent_framework_declarative import AgentFactory
Related Implementation Declarative Tool Function Pattern

Problem Statement

The @tool decorator approach tightly couples Python functions to the framework's tool registration system. In declarative agent architectures, the agent's structure, instructions, and tool definitions live in YAML files, enabling non-code configuration changes. A mechanism is needed to bridge plain Python callables into the YAML-defined tool graph without requiring decorator-based registration. The Declarative Tool Binding pattern solves this by using a dictionary-based mapping at agent creation time.

Description

In the declarative approach, the tool-use protocol operates differently from the decorator-based pattern:

  1. The developer authors a YAML agent definition that declares tools by kind, name, and a bindings key.
  2. The developer writes plain Python functions with standard type annotations and docstrings -- no @tool decorator is required.
  3. At agent creation time, the developer passes a bindings dictionary to AgentFactory, where each key matches the YAML tool's bindings key and each value is the corresponding Python callable.
  4. The AgentFactory resolves the YAML tool definitions against the bindings, wiring each tool name to its implementation.
  5. At runtime, when the LLM generates a tool call, the framework dispatches it to the bound Python function.

Theoretical Basis

Separation of Definition and Implementation

The declarative approach separates what a tool is (its name, description, and parameter schema in YAML) from how it works (the Python function body). This separation enables:

  • Non-developer configuration -- YAML files can be authored and modified by non-programmers to adjust agent behavior.
  • Environment-specific binding -- The same YAML definition can be bound to different Python implementations depending on the deployment context (e.g., mock functions for testing, real implementations for production).
  • Late binding -- Tool implementations are resolved at agent creation time rather than at module import time, providing flexibility in dependency injection.

Binding Key Contract

The critical invariant in this pattern is the key match:

# The bindings dictionary key...
bindings = {"get_weather": get_weather}

# ...must match the YAML tool's bindings key:
# tools:
#   - kind: function
#     name: GetWeather
#     bindings:
#       get_weather: get_weather

If the binding key in Python does not match the key declared in the YAML bindings section, the tool will not be wired and the agent will fail to resolve the tool at runtime.

No Decorator Required

Unlike the @tool decorator pattern (see Function Tool Definition), declarative tool functions are plain Python functions. The framework does not need to introspect them for schema generation at decoration time because the schema is already defined in the YAML file. The function only needs to:

  • Accept the parameters defined in the YAML tool schema.
  • Return a value that the framework can serialize back to the LLM.

Contrast with @tool Decorator

Aspect @tool Decorator Declarative Binding
Registration At import time via decorator At agent creation time via bindings dict
Schema source Generated from Python type hints Defined in YAML tool definition
Function requirements Must be decorated with @tool Plain Python function, no decorator
Configuration coupling Code and schema are co-located Schema in YAML, implementation in Python
Flexibility Fixed at decoration time Swappable at factory instantiation

Usage

Step 1: Define the YAML Tool

type: prompt
name: WeatherAgent
instructions: You help users check the weather.
tools:
  - kind: function
    name: GetWeather
    description: Get weather for a location
    bindings:
      get_weather: get_weather
    parameters:
      type: object
      properties:
        location:
          type: string
          description: City name
        unit:
          type: string
          enum: ["celsius", "fahrenheit"]
          default: "celsius"
      required:
        - location

Step 2: Implement the Python Function

from typing import Literal

# Plain Python function -- no @tool decorator needed
def get_weather(
    location: str,
    unit: Literal["celsius", "fahrenheit"] = "celsius",
) -> str:
    """A simple function tool to get weather information."""
    return f"The weather in {location} is 22 degrees {unit}."

Step 3: Bind via AgentFactory

from agent_framework_declarative import AgentFactory

factory = AgentFactory(
    client=client,
    bindings={"get_weather": get_weather},  # key matches YAML bindings
)

agent = factory.create_agent_from_yaml(yaml_str)

Usage Guidelines

  1. Match binding keys exactly -- The key in the Python bindings dictionary must be identical to the key in the YAML bindings section. Mismatches will cause runtime errors.
  2. Keep functions self-contained -- Since the YAML defines the schema, the Python function should focus on implementation logic. Type hints and docstrings are still recommended for developer documentation.
  3. Use typing for clarity -- Even though the schema lives in YAML, annotating the Python function with proper types (str, Literal, etc.) improves code readability and enables IDE support.
  4. Test bindings independently -- Because the function is a plain callable, it can be unit-tested in isolation without involving the YAML loading or agent creation machinery.

Related

Categories

Page Connections

Double-click a node to navigate. Hold to expand connections.
Principle
Implementation
Heuristic
Environment