Skip to content

AFM Specification v0.3.0

1. Introduction

AFM (Agent-Flavored Markdown) is a markdown-based format to define AI agents. It allows agents to be written in text once and reused across different platforms.

This document details the AFM file format, its syntax, and the schema for defining an agent.

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.

1.1. Key Goals of AFM

AFM unifies agent definition through a text-based standard:

  • No Code: AFM enables defining an agent's instructions, tools, and configuration in a simple, declarative, text-based format, moving away from complex, imperative code. The markdown-based syntax is intuitive for both developers and non-technical stakeholders to read, write, and understand.

  • Portable: By defining agents declaratively in text rather than code, AFM enables the same agent definition to be interpreted and deployed across diverse platforms and tools.

  • Unified: AFM provides a clean, declarative model that works seamlessly for both developers writing code and those using visual, low-code interfaces. The same AFM file can power both experiences.

  • Adaptable: AFM is designed to be flexible and extensible, allowing the standard to evolve as AI technologies and requirements change.

2. Core Concepts

AFM defines the following core concepts:

  • Agent: The primary entity defined by an AFM file, representing an AI agent.
  • Role: The agent's purpose and responsibilities.
  • Instructions: Directives governing the agent's behavior.
  • Details: Metadata describing the agent (name, version, author, etc.).
  • Model: The AI model powering the agent.
  • Tools: External tools and services available to the agent.
  • Interface: How the agent is invoked and its input/output contract.

Agent Memory

Given the lack of standardization, AFM does not prescribe a standard for agent memory yet.

3. File Extension

An agent definition file MUST use the .afm.md or .afm extension.

4. Syntax Overview

4.1. Basic Structure

An AFM file is structured into two main sections: the front matter and the agent declaration.

  • Front Matter: Contains metadata about the agent.
  • Markdown Body: Contains the agent's definition.

4.2. Front Matter

The front matter is a YAML block at the top of the file, enclosed by --- lines. Refer to the YAML specification for more details on YAML syntax.

This section contains metadata about the agent. These metadata fields are OPTIONAL and can be used to provide additional context or configuration for the agent.

Section Description
Agent Details Information about the agent, such as its name, description, version, and author.
Agent Model Defines the AI model that powers the agent.
Agent Interfaces Defines how the agent is invoked and its input/output signature.
Agent Tools Defines external tools available to the agent (e.g., via MCP).
Agent Execution Runtime execution configuration like iteration limits.

Refer to the AFM Schema for a complete list of fields and their meanings.

4.3. Markdown Body

This section contains the detailed instructions that guide the agent's behavior.

Users can use markdown syntax to format the text, including headings, lists, links, and code blocks.

The Markdown body MUST contain the following headings, with corresponding content.

  • # Role: Defines the agent's purpose and responsibilities. This section describes what the agent does and the context in which it operates. This content typically forms the opening context of the system prompt.
  • # Instructions: Provides directives that shape the agent's behavior, capabilities, and operational guidelines. This section contains the core logic and rules that govern how the agent processes inputs and generates outputs.

4.4. Example

Basic AFM File Example

Here is a simple example of an AFM file:

---
spec_version: "0.3.0"
name: "Math Tutor"
description: "An AI assistant that helps with math problems"
version: "1.0.0"
max_iterations: 20
interfaces:
  - type: consolechat
tools:
  mcp:
    - name: "math_operations"
      transport:
        type: "http"
        url: "${env:MATH_MCP_SERVER}"
---

# Role

You are an experienced math tutor capable of assisting students with mathematics problems, providing explanations, step-by-step 
solutions, and practice exercises.

# Instructions

You are a knowledgeable and patient math tutor who helps students understand mathematical concepts. Provide clear, step-by-step 
explanations for math problems, using simple language and avoiding jargon unless explaining it. 

When solving problems, show all work and explain each step. Use the available math operations tools when performing calculations. 
Explain mathematical concepts with real-world examples when possible. Be encouraging and supportive of students' efforts, ask clarifying 
questions if a problem is not clearly stated, provide multiple approaches to solving problems when applicable, help students identify 
and correct their mistakes.

5. Schema Definitions

This section defines the schema for the Front Matter. For clarity, the schema is divided into several subsections, each detailing a specific aspect of the Agent.

5.1. Agent Details

This section defines the schema for agent-specific metadata. It is OPTIONAL but recommended for clarity and organization.

AFM implementations SHALL use this section to display the agent's metadata in user interfaces to provide better user experience for end users.

5.1.1. Schema Overview

The agent metadata fields are specified in the YAML front matter of an AFM file:

spec_version: string   # AFM specification version (e.g., "0.3.0")
name: string           # The name of the agent
description: string    # Brief description of the agent's purpose and functionality
version: string        # Semantic version (e.g., "1.0.0")
author: string         # Single author in format "Name <Email>"
authors:               # Takes precedence over the 'author' field if both exist
  - string             # Multiple authors, each in format "Name <Email>"
provider: object       # Agent provider
  name: string         # Name of the organization
  url: string          # URL to the organization's website
icon_url: string       # URL to an icon representing the agent
license: string        # License under which the agent is released

5.1.2. Field Definitions

Each field serves a specific purpose in defining and organizing the agent:

Key Type Required Description
spec_version string No Version of the AFM specification this file conforms to (e.g., "0.3.0").
This is OPTIONAL but recommended for compatibility.
AFM implementations MAY use this field to validate compatibility and provide warnings for mismatched spec versions.
name string No Identifies the agent in human-readable form.
Default: inferred from the filename of the AFM file.
AFM implementations SHALL use this field to display the agent's name in user interfaces.
description string No Provides a concise summary of what the agent does.
Default: inferred from the markdown body # Role section.
AFM implementations SHALL use this field to display the agent's description in user interfaces.
version string No Semantic version of the agent definition (MAJOR.MINOR.PATCH).
Default: "0.0.0".
AFM implementations SHALL use this field to display the agent's version in user interfaces.
author string No Single author in format Name <Email>.
Credits the creator of the agent definition. If both author and authors fields are provided, authors takes precedence.
authors string[] No Multiple authors, each in format Name <Email>.
Credits the creators of the agent definition. Takes precedence over author if both exist.
icon_url string No URL to an icon representing the agent.
This is OPTIONAL but recommended for visual representation in user interfaces.
AFM implementations SHALL use this field to display the agent's icon in user interfaces.
provider object No Information about the organization providing the agent.
This is OPTIONAL but recommended for attribution.
See the Provider Object below for details.
license string No License under which the agent definition is released.
This is OPTIONAL but recommended for clarity.

Provider Object:

Key Type Required Description
name string No Name of the organization providing the agent.
url string No URL to the organization's website.

5.1.3. Example Usage

The following example demonstrates a valid agent metadata section as specified in Section 5.1. This YAML front matter illustrates the use of recommended and optional fields for agent definition:

---
spec_version: "0.3.0"
name: "Math Tutor"
description: "An AI assistant that helps with math problems"
version: "1.2.0"
authors:
  - "Jane Smith <jane@example.com>"
  - "John Doe <john@example.com>"
provider:
  name: "Example AI Solutions"
  url: "https://example.com"
icon_url: "https://example.com/icons/math-tutor.png"
license: "MIT"
---

5.2. Agent Model

This section specifies the AI model or language model that powers the agent. It is OPTIONAL and defines how to access and authenticate with the model service.

5.2.1. Field Definitions

Key Type Required Description
name string No Model identifier or name.
provider string No The organization or service providing the model (e.g., "openai", "anthropic").
url string No The URL endpoint for the model service.
authentication object No Authentication configuration for accessing the model. See Section 5.6 for the schema.

5.2.2. Schema Overview

model:
  name: string             # Optional model name or identifier
  provider: string         # Optional model provider (e.g., "openai", "anthropic")
  url: string              # Optional model service endpoint URL
  authentication: object   # Optional authentication configuration

5.2.3. Example Usage

model:
  name: "gpt-4-turbo"
  provider: "openai"
  url: "https://api.openai.com/v1/chat/completions"
  authentication:
    type: "api-key"
    api_key: "${env:OPENAI_API_KEY}"

5.3. Agent Interfaces

This section defines how an agent can be interacted with or triggered. An agent can have multiple interfaces, allowing it to be accessed in different ways. It is OPTIONAL and specifies how the agent receives inputs and produces outputs.

If the interfaces field is not explicitly defined in the front matter, AFM implementations MUST assume a default interface of type consolechat. In this default mode, the agent SHALL be invoked as a command-line chat interface: it MUST accept a single string input (user message) and MUST produce a single string output (agent reply).

Users can override these defaults by specifying the interfaces field in the front matter as an array of interface definitions. AFM implementations SHALL use these definitions to generate the agent's callable interfaces and to ensure consistent behavior across different platforms.

5.3.1. Interface Types

The interface.type field MUST be one of the following values:

Value Description
consolechat The agent is exposed as a command-line/terminal chat interface for interactive console-based conversations.
webchat The agent is exposed as a web-based chat interface, accessible through browsers with a conversational UI.
webhook The agent is exposed as a webhook endpoint and supports subscription details (e.g., WebSub hub integration).

Each interface type defines how the agent is triggered and interacted with. Implementations MAY support all three types as described above.

5.3.2. Schema Overview

interfaces:
  - type: consolechat | webchat | webhook
    prompt: string       # For webhook type: template string for constructing the user prompt for the agent run
    signature:
      input: object      # JSON Schema object defining input parameters
      output: object     # JSON Schema object defining output parameters
    # Optional, depending on type:
    exposure:            # For webchat/webhook types only
      http: object       # Configuration for exposing as an HTTP endpoint.
    subscription:        # For webhook type
      protocol: string   # e.g., "websub"
      hub: string        # Subscription hub URL
      topic: string      # Topic to subscribe to
      callback: string   # Callback URL for receiving events (optional, for dynamic registration)
      secret: string     # Secret for verifying webhook payloads (optional)
      authentication: object   # Authentication configuration for the subscription  (optional)

5.3.3. Field Definitions

The interfaces field is an array where each element represents an interface definition. Each interface object has the following fields:

Interface Object:

Key Type Required Description
type string Yes The agent's interface type. Must be one of:
- webchat: Web-based chat interface
- consolechat: Command-line/terminal chat interface
- webhook: Webhook endpoint with subscription support
prompt string No (webhook only) A template string for constructing the user prompt for an agent run from webhook data.
Supports variable substitution with HTTP context prefixes:
- ${http:payload.fieldname} to access webhook payload fields
- ${http:header.headername} to access HTTP headers
When provided, this templated prompt is used as the user prompt to the agent instead of passing the raw payload.
When omitted, the implementation determines how to construct the agent prompt from the webhook payload.
signature object No Defines the agent's input and output parameters. If omitted, defaults to string input and string output for consolechat and webchat types. See Signature Object.
exposure object No Configuration for how a webchat or webhook agent is exposed via HTTP. Not applicable to consolechat. See Exposure Object.
subscription object No (webhook only) Subscription configuration. See Subscription Object.
Signature Object

Defines the data contract for the agent. The input and output fields MUST conform to the JSON Schema specification, but are expressed in YAML syntax. This allows for:

  • Simple signatures (e.g., a single string, number, boolean, or array)
  • Complex, structured objects with named properties
  • Full expressiveness of JSON Schema for validation and documentation

Examples:

Single string input/output (default):

signature:
  input:
    type: string
  output:
    type: string

Complex object with properties:

signature:
  input:
    type: object
    properties:
      user_prompt:
        type: string
        description: "The user's query or request"
      context:
        type: object
        description: "Additional context for the request"
    required: [user_prompt]
  output:
    type: object
    properties:
      response:
        type: string
        description: "The agent's response to the user prompt"
      confidence:
        type: number
        description: "Confidence score for the response"
    required: [response]

Array input/output:

signature:
  input:
    type: array
    items:
      type: string
  output:
    type: array
    items:
      type: string

Default Behavior:

Default signature behavior:

  • For consolechat and webchat types: the default signature is string input and string output.

  • For webhook type: the input field MAY be omitted, as the webhook provider determines the input payload structure.

AFM implementations SHALL use this definition to generate the agent's callable interface and to ensure consistent behavior across different platforms.

Subscription Object (webhook only):

Key Type Required Description
protocol string Yes The subscription protocol (e.g., websub).
hub string No The hub to subscribe at (optional if subscription is registered manually).
topic string No The topic to subscribe to (optional if subscription is registered manually).
callback string No The callback URL where events should be delivered (optional, for dynamic or self-registration).
authentication object No Optional authentication configuration for the webhook subscription. See Section 5.6 for the schema.
secret string No A secret used to sign or verify webhook payloads (optional, for security).
Exposure Object

Applies to agents of type webchat and webhook, and defines how the corresponding services are exposed.

Key Type Required Description
http object No Defines how to expose the agent via a standard HTTP endpoint.

HTTP Object:

Key Type Required Description
path string No The URL path segment for the agent's HTTP endpoint (e.g., /math-tutor). If not specified, implementations SHOULD use /chat for webchat interfaces and /webhook for webhook interfaces.

HTTP Exposure Configuration

The http object is applicable for agents of type webchat or webhook. It defines how the agent is exposed via a standard HTTP endpoint, allowing other systems to interact with it over the web.

Default Paths:

  • webchat: If no exposure.http.path is specified, implementations SHOULD default to /chat
  • webhook: If no exposure.http.path is specified, implementations SHOULD default to /webhook

AFM does not define the HTTP methods (GET, POST, etc.) for the agent's endpoint. This is left to the implementation to decide based on the agent's functionality and requirements.

5.3.4. Example Usages

Web chat agent (default simple string):

interfaces:
  - type: webchat
    signature:
      input:
        type: string
      output:
        type: string

Web chat agent (custom with structured input/output):

interfaces:
  - type: webchat
    signature:
      input:
        type: object
        properties:
          message:
            type: string
            description: "The user's chat message"
          context:
            type: object
            description: "Additional context for the conversation"
        required: [message]
      output:
        type: object
        properties:
          reply:
            type: string
            description: "The agent's chat reply"
          confidence:
            type: number
            description: "Confidence score for the response"
        required: [reply]
    exposure:
      http:
        path: "/webchat"

Console chat agent:

interfaces:
  - type: consolechat
    signature:
      input:
        type: string
      output:
        type: string

Webhook agent (with prompt templating):

interfaces:
  - type: webhook
    prompt: |
      A new ${http:payload.event} event was received from ${http:header.User-Agent}.

      Event Details:
      - Type: ${http:payload.event}
      - Timestamp: ${http:payload.timestamp}
      - Source: ${http:payload.source}

      Payload:
      ${http:payload.data}

      Please analyze this webhook event and provide a summary of the action taken.
    signature:
      output:
        type: object
        properties:
          result:
            type: string
            description: "The agent's response to the webhook event"
        required: [result]
    subscription:
      protocol: "websub"
      hub: "https://example.com/websub-hub"
      topic: "https://example.com/events/agent"
      callback: "https://myagent.example.com/webhook-callback"
      secret: "${env:WEBHOOK_SECRET}"
    exposure:
      http:
        path: "/webhook-handler"

5.4. Tools

This section defines the tools the agent can access and use.

5.4.1. Schema Overview

The tools fields are specified in the YAML front matter of an AFM file:

tools:
  mcp: array         # List of MCP servers to connect to.

5.4.2. Field Definitions

Key Type Required Description
tools object No Container for protocol-specific tool connection configurations.
tools.mcp array No List of MCP servers to connect to. See Section 6.1 for detailed schema.

5.4.3. Example Usage

Here's a simple example of tools in an AFM file:

tools:
  mcp:
    - name: "github_api"
      transport:
        type: "http"
        url: "https://api.githubcopilot.com/mcp/"
        authentication:
          type: "bearer"
          token: "${env:GITHUB_TOKEN}"

5.5. Agent Execution

This section defines execution control and runtime behavior settings for the agent. These settings are OPTIONAL and help AFM implementations manage agent execution safely and efficiently.

5.5.1. Schema Overview

max_iterations: int    # Maximum number of iterations per agent run

5.5.2. Field Definitions

Key Type Required Description
max_iterations integer No Maximum number of iterations the agent can perform in a single run.
This helps prevent infinite loops or runaway execution.
Default: Implementation-specific (typically unlimited or a high value like 100).
AFM implementations SHOULD respect this limit and gracefully terminate agent execution when the limit is reached.

5.5.3. Example Usage

max_iterations: 50

5.6. Authentication

This section defines the generic client authentication schema that is used across different parts of the AFM specification, including MCP server connections and webhook subscriptions.

The authentication object is OPTIONAL.

5.6.1. Schema Overview

authentication:
  type: string         # Authentication scheme (bearer, jwt, oauth2, api-key, basic, etc.)
  # Additional fields depend on the type
  # Examples:
  # - For bearer: token
  # - For basic: username, password

5.6.2. Field Definitions

Authentication Object:

Key Type Required Description
type string Yes Authentication scheme (e.g., bearer, basic, jwt, oauth2).
Determines which additional fields are required or supported.
* Various Varies Additional fields are authentication-type specific. See examples below for common patterns.
Values SHOULD use variable substitution to reference credentials securely.

5.6.3. Example Usage

# Bearer token authentication
authentication:
  type: bearer
  token: "${env:API_TOKEN}"

# Basic authentication
authentication:
  type: basic
  username: "${env:API_USERNAME}"
  password: "${env:API_PASSWORD}"

6. Protocol Specifications

This section details the protocols that agents use to communicate with external systems and other agents, as referenced in the schema above.

6.1. Model Context Protocol (MCP)

The Model Context Protocol (MCP) enables agents to connect to external tools and data sources.

6.1.1. Schema Overview

mcp:
  - name: string           # Unique identifier for the server connection
    transport:
      type: string         # Transport mechanism (must be "http")
      url: string          # URL for the MCP server
      authentication:      # Optional authentication configuration
        type: string       # Authentication scheme (bearer, jwt, oauth2, etc.)
    tool_filter:           # Optional
      allow: [string]      # Whitelist of tools
      deny: [string]       # Blacklist of tools

6.1.2. Field Definitions

The mcp field is an array where each element represents an MCP server connection. Each server entry must have a unique name that identifies the connection.

MCP Server Object:

Key Type Required Description
name string Yes A unique, human-readable identifier for the connection.
transport object Yes An object defining the transport mechanism. See Transport Object below.
tool_filter object No Filter configuration for tools from this server. See Tool Filter Object below.

Transport Object:

Key Type Required Description
type string Yes Transport mechanism. Must be http.
url string Yes The URL of the MCP server.
authentication object No Authentication configuration for the connection. See Section 5.6 for the schema.

HTTP Transport Only

AFM currently supports only the streamable HTTP transport for MCP connections, but may support other transports in the future.

Tool Filter Object:

Key Type Required Description
allow string[] No A whitelist of tools to expose from this server, using just the tool name (e.g., create_issue, read_file). If specified, only these tools are available.
deny string[] No A blacklist of tools to hide from this server, using just the tool name (e.g., write_file). Applied after allow filtering.

Filter Precedence

When both allow and deny are specified, the tools in the allow list are made available and then the deny list is applied to remove specific tools from that filtered set. If only deny is specified, all tools from the server are available except those in the deny list.

6.1.3. Example Implementation

This example defines tool connections to remote MCP servers with authentication and tool filtering. Note the use of variable substitution for sensitive and/or variable input.

tools:
  mcp:
    - name: "github_mcp_server"
      transport:
        type: "http"
        url: "${env:GITHUB_MCP_URL}"
        authentication:
          type: "bearer"
          token: "${env:GITHUB_OAUTH_TOKEN}"
      tool_filter:
        allow:
          - "issues.create"
          - "repos.list"

    - name: "database_server"
      transport:
        type: "http"
        url: "${env:DATABASE_MCP_URL}"
        authentication:
          type: "bearer"
          token: "${env:DATABASE_API_KEY}"
      tool_filter:
        allow:
          - "query"
          - "search"
        deny:
          - "delete"
          - "drop_table"

7. Variable Substitution

AFM files MAY use ${...} syntax for variable substitution.

This specification defines three standard variable prefixes:

  • The env: prefix (e.g., ${env:API_TOKEN}) is specification-defined and MUST resolve to an environment variable, generally at agent load time (i.e., variable resolution for env: occurs before the agent is made available for use).
  • The http:payload prefix (e.g., ${http:payload.field}) is specification-defined for webhook interfaces and MUST resolve to the corresponding field in the incoming webhook payload at runtime. Variable resolution for http:payload occurs at runtime for each webhook invocation.
  • The http:header prefix (e.g., ${http:header.User-Agent}) is specification-defined for webhook interfaces and MUST resolve to the corresponding HTTP header value from the incoming webhook request at runtime. Header names are case-insensitive.

Implementations MAY define and support additional variable substitution conventions beyond those specified here. Common examples include file: and secret:, but these are implementation-defined and MAY vary between AFM implementations. The timing and semantics of resolution for these prefixes are determined by the implementation.

7.1. Variable Prefixes

The following table summarizes variable prefixes and their status:

Prefix Context Description Example Spec Status
env: Static Environment variable ${env:API_TOKEN} Spec-defined
http:payload Runtime (webhook) Access webhook payload fields ${http:payload.event} or ${http:payload['nested.field']} Spec-defined
http:header Runtime (webhook) Access HTTP request headers ${http:header.User-Agent} or ${http:header.X-GitHub-Event} Spec-defined
file: Static Value from external config file ${file:api.baseUrl} Implementation-defined
secret: Static Value from secrets manager ${secret:MODEL_API_KEY} Implementation-defined

Static vs Runtime Resolution:

  • Static variables (env:, file:, secret:): Resolved once when the agent is loaded or initialized
  • Runtime variables (http:payload, http:header): Resolved dynamically for each webhook invocation using request-specific data

7.2. Example Usage

Static variable substitution:

authentication:
  type: "bearer"
  token: "${env:API_TOKEN}"        # Environment variable
transport:
  url: "${file:api.baseUrl}"        # From external config file

model:
  authentication:
    type: "bearer"
    token: "${secret:MODEL_API_KEY}" # From secrets manager

Runtime variable substitution (webhook prompts):

interfaces:
  - type: webhook
    prompt: |
      New GitHub ${http:payload.action} event on repository ${http:payload.repository.full_name}

      Event: ${http:header.X-GitHub-Event}
      Sender: ${http:payload.sender.login}

      Details:
      ${http:payload}

7.3. Webhook Variable Access Patterns

When using http:payload and http:header in webhook prompts:

Payload Field Access (Specification Requirements):

  • Implementations MUST support dot notation for nested object access (e.g., ${http:payload.field.nested} resolves to the value of the nested property within the field object).
  • Implementations MUST support bracket notation for field names containing special characters or dots (e.g., ${http:payload['field.with.dots']} resolves to the value of the field.with.dots property).
  • Implementations MUST support array access by index (e.g., ${http:payload.items[0]} resolves to the first element of the items array).
  • Implementations MUST support combined access for complex paths (e.g., ${http:payload.users[0].name} or ${http:payload['special-field'][0]} resolves to the name property of the first element in the users array, or the first element of the special-field array, respectively).
  • Implementations MUST support root access, where ${http:payload} resolves to the entire payload as a JSON string.

Header Access (Specification Requirements):

  • Implementations MUST treat header names as case-insensitive (e.g., ${http:header.Content-Type} and ${http:header.content-type} MUST resolve to the same value).
  • Implementations MUST support access to headers with special characters (e.g., ${http:header.X-GitHub-Event} resolves to the value of the X-GitHub-Event header).

Error Handling: Implementations SHOULD handle missing or invalid variable references gracefully by using meaningful defaults or failing with clear error messages.

8. Future Work

This section outlines potential future enhancements to the AFM specification, including:

  • Extending tool support to include MCP tools with STDIO transport, OpenAPI-based tools for existing services, and functions as tools
  • First-class support for multi-agent interaction via the Agent-to-Agent (A2A) protocol
  • Support for an Agent memory abstraction covering common memory patterns
  • Support for Agent Identity
  • Support for additional interface types (e.g., scheduled execution, REST API)