afps-spec

Agent Flow Packaging Standard (AFPS) Specification

Copyright © 2026 Appstrate contributors. This specification is licensed under CC-BY-4.0. Code and examples are licensed under MIT.

Version 1.0 – Draft

Abstract

Agent Flow Packaging Standard (AFPS) is an open specification for declaring portable AI workflow packages. It defines a JSON-based manifest format for four package types — flows, skills, tools, and providers — along with their dependency model, schema system, archive layout, and provider authentication metadata. AFPS standardizes package definition and composition; it does not define tool-calling protocols, agent-to-agent transport, or runtime execution APIs.

Status of this Document

This document is a draft of the AFPS v1.0 specification. It is published for community review and early implementation feedback.

This draft is published for community review and early implementation feedback. It is expected to evolve based on implementation experience and community input before reaching a stable release.

Table of Contents


1. Introduction

1.1 Purpose

Agent Flow Packaging Standard (AFPS) defines a declarative package format for AI workflows and closely related package types.

The central artifact in AFPS is the flow — a package that captures the user’s intent (via a prompt.md companion file) together with everything the agent needs to fulfill it: skills, tools, provider connections, input and output schemas, and execution settings. Where other standards define agent capabilities (what an agent can do), an AFPS flow defines an objective (what the agent should accomplish).

AFPS also defines three supporting package types — skills (reusable instructions), tools (callable capabilities), and providers (service connectors) — that flows compose as dependencies.

The goal of AFPS is to let producers publish portable artifacts that describe:

AFPS is intentionally centered on package definition. It standardizes package metadata and package layout, not runtime execution APIs.

1.2 Scope

This specification defines:

This specification does not define:

AFPS is transport-agnostic: it does not prescribe how packages are fetched, transferred, or cached.

1.2.1 Relationship to Other Standards

AFPS operates at a different abstraction level than existing AI agent standards. The key distinction is between goal (what should be accomplished) and capability (how to accomplish a specific task):

┌─────────────────────────────────────────────────────────┐
│  Goal layer          AFPS Flow                           │
│                      "Process my inbox and create       │
│                       a summary of support requests"    │
│                      = the user's intent, packaged      │
├─────────────────────────────────────────────────────────┤
│  Capability layer    AFPS Skills / Tools                  │
│                      "Rewrite text in a professional    │
│                       tone" / "Fetch JSON from a URL"   │
│                      = reusable abilities the agent     │
│                        can draw on to reach the goal    │
├─────────────────────────────────────────────────────────┤
│  Connection layer    AFPS Providers                      │
│                      "Gmail via OAuth2"                 │
│                      = authenticated access to          │
│                        external services                │
└─────────────────────────────────────────────────────────┘

A flow’s prompt.md replaces what a human would type to give an agent its objective. Skills, tools, and providers are the resources the agent uses to fulfill that objective. AFPS packages all of these together into a portable, versioned artifact.

Existing standards address different concerns:

These standards are complementary and operate at different layers:

Discovery    MCP Registry / A2A Agent Cards     "where to find agents and tools"
Transport    MCP JSON-RPC / A2A Tasks            "how agents communicate at runtime"
Capability   Agent Skills / MCP Tools            "what an agent knows how to do"
Goal         AFPS Flow                            "what the agent should accomplish"
Packaging    AFPS                                 "how it is all declared and distributed"

1.3 Terminology

1.4 Conformance

The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHOULD”, “SHOULD NOT”, and “MAY” in this document are to be interpreted as described in BCP 14 [RFC 2119] [RFC 8174] when, and only when, they appear in all capitals, as shown here.

Conforming producers MUST emit manifests and package archives that satisfy the requirements in this document. Conforming consumers MUST reject malformed packages and SHOULD preserve unknown fields when round-tripping manifests. AFPS v1.0 intentionally allows extensibility: manifests and several nested objects accept additional fields unless this specification explicitly forbids them. Extension fields MUST follow the naming convention defined in §10.

2. Package Model

2.1 Package Types

AFPS defines four package types:

A package’s type field is the dispatch key used by validators and archive parsers. Producers MUST set it to exactly one of the values above.

2.2 Package Identity

Every AFPS package MUST have a scoped name of the form @scope/name. The scope and name segments MUST each match SLUG_PATTERN:

[a-z0-9]([a-z0-9-]*[a-z0-9])?

As a consequence:

The full scoped-name pattern is:

^@[a-z0-9]([a-z0-9-]*[a-z0-9])?\/[a-z0-9]([a-z0-9-]*[a-z0-9])?$

2.3 Versioning

The top-level version field MUST be a valid semantic version per [SemVer]. Registry dependency values MUST be valid semantic version ranges.

AFPS itself does not define its own range syntax. It delegates version parsing and range parsing to widely used semantic-version semantics. In practice:

If a registry supports non-version queries, it MAY resolve queries in the order exact version, dist-tag, then semver range. Exact version lookups MAY resolve yanked entries; dist-tags and ranges SHOULD prefer non-yanked versions.

2.4 Schema Version Compatibility

When a consumer encounters a manifest whose schemaVersion has a higher MAJOR number than the highest version it supports, it MUST reject the manifest and SHOULD report an error identifying the unsupported schema version. Processing a manifest with an unknown major version could lead to silent data loss or incorrect behavior.

When a consumer encounters a manifest whose schemaVersion has the same MAJOR number but a higher MINOR number than the highest version it supports, it SHOULD process the manifest on a best-effort basis. Unknown fields SHOULD be preserved. Consumers MAY emit a warning indicating that some fields may not be fully understood.

When schemaVersion is absent from a skill, tool, or provider manifest (where the field is optional), consumers SHOULD treat the package as targeting schema version 1.0.

2.5 Package Archive Format

AFPS packages are distributed as ZIP archives.

Every package archive MUST contain manifest.json at the archive root. Additional required files depend on manifest.type:

Type Required companion content
flow prompt.md at archive root, non-empty
skill SKILL.md at archive root; optional scripts/, references/, assets/ directories (see §3.3)
tool source file referenced by manifest entrypoint
provider no companion file beyond manifest.json

Producers SHOULD use the .afps file extension for package archives (e.g., customer-intake-1.0.0.afps). Consumers MUST accept archives regardless of file extension. The .afps extension is a convention for human recognition and tool association; it does not alter the archive format, which remains standard ZIP.

Consumers SHOULD sanitize ZIP entries before processing them. At minimum, entries with path traversal segments (..), absolute paths, null bytes, backslashes, __MACOSX/ prefixes, or directory-only entries SHOULD be ignored.

3. Manifest Specification

All manifests are JSON objects. Unknown top-level fields and unknown nested fields in extensible objects are allowed by the validation model and SHOULD be preserved by tooling unless a tool intentionally normalizes the manifest.

3.1 Common Fields

name

version

type

displayName

description

keywords

license

repository

schemaVersion

registryDependencies

3.2 Flow Manifest

Flow manifests extend the common fields above. A conforming flow manifest MUST include schemaVersion, displayName, author, and requires.

author

requires

providersConfiguration

input

output

config

execution

3.3 Skill Package

AFPS skill packages are a superset of the [Agent Skills] format. A valid Agent Skill directory becomes a valid AFPS skill package when a manifest.json is added alongside the existing SKILL.md. The SKILL.md format and all companion directories defined by Agent Skills are preserved unchanged.

Required files

A skill package MUST contain manifest.json and SKILL.md at the archive root. The manifest MUST validate as a common manifest with type: "skill".

SKILL.md format

SKILL.md SHOULD begin with a YAML frontmatter block followed by a Markdown body containing the skill instructions. For interoperable skill packages:

Current ZIP parsing behavior treats a missing frontmatter name as invalid content. A missing frontmatter description is tolerated but SHOULD be avoided.

The following frontmatter fields are recognized from the Agent Skills specification and SHOULD be preserved by AFPS consumers:

Field Required Description
name SHOULD Skill identifier. Max 64 characters, lowercase alphanumeric and hyphens.
description SHOULD What the skill does and when to use it. Max 1024 characters.
license MAY License name or reference to a bundled license file.
compatibility MAY Environment requirements (intended product, system packages, network access). Max 500 characters.
metadata MAY Arbitrary key-value mapping for additional metadata.
allowed-tools MAY Space-delimited list of pre-approved tools. Experimental in Agent Skills.

AFPS does not extend or modify the frontmatter vocabulary. Additional frontmatter fields defined by future Agent Skills revisions SHOULD be preserved by AFPS consumers.

Optional companion directories

Skill packages MAY include the following directories, as defined by Agent Skills:

Additional files and directories beyond those listed above MAY be included in the archive. Consumers SHOULD preserve them when round-tripping packages.

Progressive disclosure

Skill content is designed for efficient context usage across three levels:

  1. Metadata (~100 tokens): the name and description frontmatter fields, loaded at startup for skill discovery;
  2. Instructions (< 5000 tokens recommended): the full SKILL.md body, loaded when the skill is activated;
  3. Resources (as needed): files in scripts/, references/, assets/, loaded only when required.

Producers SHOULD keep SKILL.md under 500 lines and move detailed reference material to separate files.

3.4 Tool Package

A tool package declares a single callable capability and bundles its implementation source code. The manifest describes the tool interface; the source file provides the implementation.

Required files

A tool package MUST contain manifest.json at the archive root and an implementation source file at the path declared by the entrypoint field.

entrypoint

tool

tool.name

tool.description

tool.inputSchema

AFPS does not define how consumers load or execute the source file. A consumer MAY import it as a module, spawn it as a subprocess, compile it, or use any other strategy. The tool object in the manifest provides sufficient metadata for tool discovery and invocation without executing the source code.

3.5 Provider Package

A provider package is manifest-only. It MUST contain a definition object describing authentication mode and related metadata. It MAY additionally contain presentation fields such as displayName, description, iconUrl, categories, and docsUrl, plus an optional setupGuide.

definition

setupGuide

4. Dependency Model

4.1 Dependency Declaration

The following diagram illustrates how a flow composes its dependencies:

                  ┌────────────────────────────────┐
                  │  @acme/customer-intake          │
                  │  type: flow                     │
                  │  prompt.md (objective)           │
                  └──────┬─────────────────────────┘
                         │
          ┌──────────────┼──────────────┐
          │              │              │
          ▼              ▼              ▼
  ┌──────────────┐ ┌────────────┐ ┌────────────┐
  │ @acme/gmail  │ │ @acme/     │ │ @acme/     │
  │ provider     │ │ rewrite-   │ │ http-tools │
  │ (OAuth2)     │ │ tone       │ │ tool       │
  │              │ │ skill      │ │            │
  └──────────────┘ └────────────┘ └────────────┘
       requires            requires          requires
       + registryDeps      + registryDeps    + registryDeps

AFPS distinguishes two dependency mechanisms that serve different audiences and operate at different times:

The distinction exists because these mechanisms address different concerns:

Aspect requires registryDependencies
Scope Flows only All package types
Value format Opaque strings (exact versions, *) Semver ranges (^1.0.0, ~2.1)
Audience Flow runner / executor Registry / installer
Timing Runtime — validated at execution Publish-time — resolved at installation
Purpose “What must be loaded to run?” “What must be installed to distribute?”

For a typical flow, the same packages appear in both fields: registryDependencies ensures they can be installed from a registry, and requires ensures they are loaded at runtime. However, the two are not redundant:

The registryDependencies maps are the source of truth for dependency extraction and cycle detection.

Values under requires.providers, requires.skills, and requires.tools are strings but are not semver-validated by the core manifest schema. For interoperability, producers SHOULD use exact versions or *.

Registries that automatically install provider dependencies for flows SHOULD require every provider listed in requires.providers to also appear in registryDependencies.providers.

4.2 Version Range Resolution

When resolving a registry dependency:

  1. a consumer MUST reject invalid semver range syntax;
  2. a registry SHOULD select the highest version satisfying the range;
  3. exact version queries MAY resolve a yanked release;
  4. dist-tag and range resolution SHOULD ignore yanked releases; and
  5. prerelease behavior SHOULD follow the underlying semver implementation.

4.3 Circular Dependency Detection

Self-reference is a cycle. Transitive cycle detection SHOULD traverse registry dependencies breadth-first so that a registry can:

A cycle report SHOULD include the publishing package id and the discovered cycle path, for example:

@example/a -> @example/b -> @example/a

4.4 Provider Configuration

providersConfiguration is keyed by provider package id. The interoperable keys defined in AFPS v1.0 are:

If connectionMode is omitted, many consumers treat it as user, but no manifest-level default is injected by validation.

5. Schema System

AFPS uses a constrained JSON-object schema model rather than the full JSON Schema vocabulary. The container schema MUST be an object with type: "object" and a properties record. Property definitions are intentionally small and extensible.

5.1 JSON Schema Properties

type

description

default

enum

format

placeholder

5.2 File Type Extensions

accept

maxSize

multiple

maxFiles

5.3 Schema Object Structure

An AFPS schema container MUST have:

It MAY also contain:

AFPS v1.0 does not define nested property schemas, array item schemas, or full JSON Schema composition keywords. Properties with type: "object" or type: "array" are therefore shallow hints unless a consumer defines additional behavior.

Because the schema validator is extensible, consumers SHOULD preserve unknown property keywords that they do not understand.

5.4 Input, Output, and Config Schemas

input, output, and config all use the same wrapper shape:

{
  "schema": {
    "type": "object",
    "properties": {}
  }
}

The wrapper object is required when any of these sections are present. A bare schema object is not valid in those locations.

Although the three sections share the same structural format, they have distinct semantics and lifecycles:

Section Lifecycle Timing Description
input Per-execution Supplied each time the flow runs Data the user provides for a specific run (e.g., a search query, a file to process).
output Per-execution Produced at the end of each run Structured result the flow returns (e.g., a summary, a report).
config Per-deployment Set once during setup, reused across runs Settings that remain constant across executions (e.g., preferred language, notification threshold).

A consumer SHOULD prompt for input values at each execution and SHOULD persist config values so they do not need to be re-entered.

6. Execution Model

6.1 Execution Context

A flow package MUST include a non-empty prompt.md companion file. That file contains the primary instructions for the flow.

A consumer MAY construct an execution context from:

AFPS does not define prompt templating, state persistence, scheduling, or transport semantics. Those concerns are out of scope.

6.2 Timeout and Retry

execution.timeout is a numeric timeout hint expressed in seconds. execution.outputRetries is a numeric retry hint constrained to the inclusive range 0..5.

AFPS v1.0 does not impose manifest-level defaults for either field. If a consumer chooses local defaults, it SHOULD document them separately from the manifest itself.

7. Provider Authentication

7.1 Auth Modes

definition.authMode MUST be one of:

7.2 OAuth2 Configuration

For oauth2 providers:

7.3 OAuth1 Configuration

For oauth1 providers:

7.4 Credential Schema

For api_key, basic, and custom providers:

The credentialSchema object SHOULD follow the AFPS schema format defined in §5 (Schema System) — that is, type: "object" with a properties record — but the manifest validator accepts any JSON object. Each property defines a credential field the user must supply.

The optional fields credentialFieldName, credentialHeaderName, and credentialHeaderPrefix MAY be used to describe how credentials are transmitted.

7.5 URI Restrictions

authorizedUris MAY restrict which upstream URIs a provider is intended to access. allowAllUris MAY be used as an explicit override. If omitted, common consumers resolve allowAllUris as false.

7.6 Setup Guide

setupGuide.callbackUrlHint MAY provide a human-facing callback hint, often including a placeholder such as ``.

setupGuide.steps MAY contain an ordered list of setup steps. Each step MUST have a label and MAY have a url.

For interoperability, availableScopes SHOULD be an array of objects with value and label keys, even though the manifest validator accepts any JSON values in that array.

8. Security Considerations

AFPS packages describe AI workflows that may access external services, process user data, and execute code. Implementers MUST consider the following threats.

8.1 Archive Processing

ZIP archives are a well-known vector for path traversal and denial-of-service attacks. Consumers MUST:

Consumers SHOULD ignore __MACOSX/ directories and other platform-specific metadata entries.

8.2 Tool Code Execution

Tool packages (§3.4) contain source code that consumers may load and execute. This is the highest-risk surface in the AFPS model:

AFPS does not define how tool code is loaded or executed. Consumers are responsible for implementing appropriate security measures for their execution environment.

8.3 Credential Handling

Provider packages (§3.5, §7) describe authentication configurations that involve OAuth tokens, API keys, and other secrets:

8.4 Prompt Injection

Flow packages include a prompt.md companion file whose content is typically sent to a language model. Malicious or compromised packages can embed prompt injection attacks:

8.5 Supply Chain

Packages distributed through registries are subject to supply chain attacks including typosquatting, dependency confusion, and malicious updates:

8.6 URI Restrictions

Provider definitions include authorizedUris to restrict which upstream endpoints a provider can access:

9. Privacy Considerations

AFPS packages may process personally identifiable information (PII) through flow inputs, provider connections, and execution outputs:

Implementers operating in jurisdictions with data protection regulations (e.g., GDPR, CCPA) SHOULD consult their compliance requirements for the handling of user data within AI workflows.

10. Extensibility

AFPS manifests and several nested objects (such as requires, execution, registryDependencies, and definition) accept additional fields beyond those defined in this specification. This design allows producers and consumers to experiment with new metadata without requiring a specification revision.

10.1 Extension Field Convention

Fields that are not defined by this specification MUST use a name prefixed with x- followed by a vendor or project identifier, for example:

{
  "name": "@example/my-flow",
  "version": "1.0.0",
  "type": "flow",
  "x-acme-priority": "high",
  "x-acme-cost-center": "engineering"
}

The x- prefix signals that the field is an extension and is not part of the normative AFPS vocabulary. This convention:

Producers MUST NOT use the x- prefix for fields that are defined by this specification. Consumers MUST NOT reject manifests that contain x--prefixed fields. Consumers MAY ignore extension fields they do not understand.

10.2 Future Standard Fields

When an extension field gains broad adoption across multiple implementations, it MAY be promoted to a standard field in a future specification revision. Upon promotion, the unprefixed field name becomes normative and the x--prefixed version becomes deprecated.

11. References

Normative References

Informative References


Appendices

Appendix A. Field Reference Table

Field Context Type Requirement Constraints / Notes Default
name all manifests string MUST scoped name none
version all manifests string MUST valid semver version none
type all manifests string MUST flow\|skill\|tool\|provider none
displayName all manifests string MUST for flow; SHOULD for skill, tool, and provider flow value min length 1 none
description all manifests string MAY free text none
keywords all manifests string[] MAY arbitrary strings none
license all manifests string MAY free text none
repository all manifests string MAY URI recommended none
registryDependencies all manifests object MAY optional dependency maps none
registryDependencies.skills all manifests map MAY keys scoped names, values valid semver ranges none
registryDependencies.tools all manifests map MAY keys scoped names, values valid semver ranges none
registryDependencies.providers all manifests map MAY keys scoped names, values valid semver ranges none
author flow string MUST free text none
requires flow object MUST optional providers, skills, tools maps none
requires.providers flow map MAY keys scoped names, values opaque strings none
requires.skills flow map MAY keys scoped names, values opaque strings none
requires.tools flow map MAY keys scoped names, values opaque strings none
providersConfiguration flow map MAY keyed by provider id none
providersConfiguration.<id>.scopes flow string[] MAY requested scopes none
providersConfiguration.<id>.connectionMode flow string MAY user\|admin consumer-defined
input flow object MAY per-execution data; requires schema child none
input.schema flow object MUST if input present AFPS schema object none
output flow object MAY per-execution result; requires schema child none
output.schema flow object MUST if output present AFPS schema object none
config flow object MAY per-deployment settings; requires schema child none
config.schema flow object MUST if config present AFPS schema object none
entrypoint tool string MUST relative path to source file none
tool tool object MUST tool interface declaration none
tool.name tool string MUST non-empty tool identifier none
tool.description tool string MUST tool description for agents none
tool.inputSchema tool object MUST JSON Schema for tool parameters none
execution flow object MAY extensible none
schemaVersion all manifests string MUST for flow; MAY for all others MAJOR.MINOR format; producers MUST emit 1.0 for this draft none
execution.timeout flow number MAY numeric timeout hint, in seconds none
execution.outputRetries flow number MAY integer, inclusive range 0..5 none
definition provider object MUST extensible; contains auth metadata none
definition.authMode provider string MUST oauth2\|oauth1\|api_key\|basic\|custom none
definition.authorizationUrl provider string MUST for oauth2 URI recommended none
definition.tokenUrl provider string MUST for oauth2 URI recommended none
definition.refreshUrl provider string MAY URI recommended consumer-defined
definition.defaultScopes provider string[] MAY default requested scopes consumer-defined
definition.scopeSeparator provider string MAY OAuth scope separator consumer-defined
definition.pkceEnabled provider boolean MAY PKCE flag consumer-defined
definition.tokenAuthMethod provider string MAY token endpoint auth hint none
definition.authorizationParams provider object MAY free-form parameter map consumer-defined
definition.tokenParams provider object MAY free-form parameter map consumer-defined
definition.credentialSchema provider object MUST for api_key, basic, custom SHOULD follow AFPS schema format; validator accepts any object none
definition.credentialFieldName provider string MAY logical credential field none
definition.credentialHeaderName provider string MAY HTTP header name none
definition.credentialHeaderPrefix provider string MAY HTTP header prefix none
definition.authorizedUris provider string[] MAY allowed upstream URI patterns none
definition.allowAllUris provider boolean MAY unrestricted upstream access consumer-defined
definition.requestTokenUrl provider string MUST for oauth1 URI recommended none
definition.accessTokenUrl provider string MUST for oauth1 URI recommended none
definition.availableScopes provider array MAY interoperable form is { value, label }[] none
iconUrl provider string MAY URI recommended none
categories provider string[] MAY arbitrary strings consumer-defined
docsUrl provider string MAY URI recommended none
setupGuide provider object MAY setup metadata none
setupGuide.callbackUrlHint provider string MAY callback placeholder text none
setupGuide.steps provider object[] MAY ordered setup steps none
setupGuide.steps[].label provider string MUST if step present non-empty recommended none
setupGuide.steps[].url provider string MAY URI recommended none
SKILL.md frontmatter name skill content string SHOULD max 64 chars, lowercase alphanumeric and hyphens none
SKILL.md frontmatter description skill content string SHOULD max 1024 chars; missing value warns none
SKILL.md frontmatter license skill content string MAY license name or file reference none
SKILL.md frontmatter compatibility skill content string MAY max 500 chars; environment requirements none
SKILL.md frontmatter metadata skill content map MAY arbitrary string key-value pairs none
SKILL.md frontmatter allowed-tools skill content string MAY space-delimited tool list; experimental none
scripts/ skill archive directory MAY executable code for agents none
references/ skill archive directory MAY additional documentation none
assets/ skill archive directory MAY static resources, templates none
x-* any extensible object any MAY extension fields MUST use x- prefix (§10) none

Appendix B. Regex Patterns

SLUG_PATTERN         = [a-z0-9]([a-z0-9-]*[a-z0-9])?
SLUG_REGEX           = ^[a-z0-9]([a-z0-9-]*[a-z0-9])?$
SCOPED_NAME_REGEX    = ^@[a-z0-9]([a-z0-9-]*[a-z0-9])?\/[a-z0-9]([a-z0-9-]*[a-z0-9])?$
SCHEMA_VERSION_REGEX = ^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$
EXTENSION_FIELD      = ^x-.+$

Semantic-version and range validation are delegated to semver parsing functions rather than regexes.

Appendix C. Default Values

AFPS v1.0 validation does not inject manifest defaults. Omitted optional fields remain omitted.

Common consumer-side defaults observed in interoperable implementations include:

Field Resolved default Notes
definition.authMode oauth2 provider resolution default when absent in raw extraction
definition.defaultScopes [] resolved provider definition
definition.scopeSeparator " " resolved provider definition
definition.pkceEnabled true resolved provider definition
definition.authorizationParams {} resolved provider definition
definition.tokenParams {} resolved provider definition
definition.allowAllUris false resolved provider definition
categories [] resolved provider definition
providersConfiguration.<id>.connectionMode user common consumer default
schemaVersion 1.0 common consumer default for new flows
execution.timeout 300 common consumer default for new flows
execution.outputRetries 2 common consumer default for new flows

These defaults are non-normative unless a producer explicitly writes them into the manifest.

Appendix D. Origins

This specification was initially drafted by Appstrate and published as an independent open standard. The normative content of this specification (§1–§10) defines the standard independently of any specific implementation. Conforming implementations MAY use different internal structures, validation strategies, or execution models while maintaining specification compliance.

See IMPLEMENTATIONS.md for known implementations.