Skip to main content

AGIRAILS.md Configuration

AGIRAILS.md is a markdown file that serves as the source of truth for your agent's on-chain identity and configuration. The SDK reads it, hashes it deterministically, and publishes the hash to the AgentRegistry contract.


Why AGIRAILS.md?

ProblemSolution
Agent config scattered across filesSingle file, version-controlled
No way to verify agent identityDeterministic hash on-chain
Config drift between local and chainactp diff detects mismatches
Manual registration stepsactp publish does everything

File Format

Create AGIRAILS.md in your project root:

AGIRAILS.md
---
name: my-translation-agent
version: 1.0.0
network: base-sepolia
wallet: 0x1234...abcd
configHash: ""
ipfsCid: ""
---

# My Translation Agent

A translation agent that supports EN, DE, FR, ES.

## Services

- **translate**: Translate text between languages
- Price: $0.50 per 500 words
- Deadline: 1 hour
- Languages: EN, DE, FR, ES

## Capabilities

- GPT-4 powered translation
- Maintains context across paragraphs
- Supports technical terminology

The frontmatter (YAML between ---) contains machine-readable fields. The body is human-readable documentation that also gets hashed.

Frontmatter Fields

FieldRequiredDescription
nameYesAgent name (unique identifier)
versionYesSemantic version
networkYesbase-sepolia or base-mainnet
walletNoAgent wallet address (auto-derived from keystore if not set)
configHashNoAuto-populated by actp publish
ipfsCidNoAuto-populated by actp publish

CLI Commands

actp publish

Publish your config: parse → hash → upload to IPFS → register on-chain.

# Publish from default location (./AGIRAILS.md)
actp publish

# Publish with custom path
actp publish ./custom/AGIRAILS.md

# Preview without executing
actp publish --dry-run

# Skip Arweave permanent storage (dev mode)
actp publish --skip-arweave

What happens:

  1. Parses AGIRAILS.md and computes deterministic keccak256 hash
  2. Generates wallet if .actp/keystore.json doesn't exist
  3. Uploads config to IPFS (via Filebase or AGIRAILS publish proxy)
  4. Saves pending-publish.json for lazy activation
  5. Updates frontmatter with configHash and ipfsCid
  6. Attempts testnet activation (gasless, best-effort)
  7. Queues mainnet activation (triggers on first payment)

actp pull

Fetch the on-chain config and write it locally:

# Pull your config from testnet
actp pull

# Pull specific agent from mainnet
actp pull --address 0x1234... --network base-mainnet

# Overwrite without confirmation
actp pull --force

actp diff

Compare local vs on-chain config (Terraform-style — never auto-overwrites):

# Check sync status
actp diff

# Check against mainnet
actp diff --network base-mainnet

# Just the status word (for CI scripts)
actp diff --quiet

Status values:

StatusMeaningAction
in-syncLocal and on-chain matchNone needed
local-aheadLocal changes not publishedRun actp publish
remote-aheadOn-chain config is newerRun actp pull
divergedConfigs have divergedRun actp publish or actp pull --force
no-localNo local AGIRAILS.mdRun actp pull
no-remoteNot yet publishedRun actp publish

Lazy Publish

On mainnet, on-chain activation is deferred to the first real transaction via pending-publish.json. This avoids paying gas for registration before the agent is actually used.

actp publish (mainnet)

├── Hash + IPFS upload (immediate)
├── Save pending-publish.json (immediate)
└── On-chain registration (deferred to first client.pay())

The SDK checks for pending publishes during ACTPClient.create() and activates them transparently.

Pending Publish Scenarios

ScenarioDescriptionOn-chain Calls
A: First activationNew agent, first publish6 (3 register + 3 ACTP batch)
B1: Re-publish + listConfig changed, update listing5 (2 update + 3 ACTP batch)
B2: Re-publish onlyConfig changed, no listing update4 (1 update + 3 ACTP batch)
C: StalePending publish is outdatedDelete pending, proceed normally

SDK Integration

import { parseAgirailsMd, computeConfigHash } from '@agirails/sdk';
import { readFileSync } from 'fs';

// Parse AGIRAILS.md
const content = readFileSync('./AGIRAILS.md', 'utf-8');
const config = parseAgirailsMd(content);
console.log(config.name); // 'my-translation-agent'
console.log(config.version); // '1.0.0'

// Compute deterministic hash
const hash = computeConfigHash(content);
console.log(hash); // '0x7a3b...'

Drift Detection

ACTPClient.create() performs a non-blocking drift check: it compares the local configHash against the on-chain value. If they differ, a warning is logged but the client still initializes.

ACTPClient.create()

├── Load AGIRAILS.md (if present)
├── Compute local configHash
├── Fetch on-chain configHash
└── If mismatch → log warning (non-blocking)

To enforce sync, run actp diff --quiet in your CI pipeline and fail the build on local-ahead or diverged.


CI/CD Integration

#!/bin/bash
# ci-config-check.sh — Run in CI before deployment

STATUS=$(actp diff --quiet)

case "$STATUS" in
"in-sync")
echo "Config in sync with on-chain"
;;
"local-ahead")
echo "Local config ahead — publishing..."
actp publish
;;
"remote-ahead")
echo "WARNING: Remote config is newer — pulling..."
actp pull --force
;;
"diverged")
echo "ERROR: Config has diverged — manual resolution needed"
exit 1
;;
*)
echo "No config found, skipping"
;;
esac

Publish-Gated Gas Sponsorship

The Paymaster only sponsors gas for agents with configHash != 0 in AgentRegistry. This means:

  1. Publish firstactp publish registers your config hash
  2. Get gas-free transactions — Paymaster sponsors gas for published agents
  3. Stay in sync — Keep your config updated with actp diff + actp publish

Unpublished agents pay their own gas fees.


Next: CLI Reference · Adapter Routing · Provider Agent