The API Reference Generator
The API Reference Generator: walk the registry, emit reference docs for every capability - types, enums, bounds, policies - straight from the contracts that VALIDATE the calls. Documentation that enforces itself cannot lie about what it accepts.
Data & Pipelines
Round 6
Piotr Solnica
exit 0
bundle exec ruby examples/api_reference.rb
a real captured run
# API Reference _Generated from the same contracts that validate every call._ ## `transfer_funds` v1.2.0 Move money between accounts ### Inputs | Field | Type | Required | Constraints | Description | |-------|------|----------|-------------|-------------| | `from_account` | string | yes | non-empty | Source account id | | `to_account` | string | yes | non-empty | Destination account id | | `amount_cents` | number | yes | >= 1; <= 10000000 | Amount in cents | | `memo` | string | no | | Optional statement memo | ### Policies - **no_self_transfer** (checks `from_account`, `to_account`): source and destination must differ ### Outputs | Field | Type | Required | Constraints | Description | |-------|------|----------|-------------|-------------| | `transfer_id` | string | yes | | | | `settled` | boolean | yes | | | ## `schedule_payout` v2.0.0 Schedule a payout to a bank account ### Inputs | Field | Type | Required | Constraints | Description | |-------|------|----------|-------------|-------------| | `amount_cents` | number | yes | >= 100 | | | `speed` | string | yes | one of: standard, instant | | | `currency` | string | yes | one of: usd, eur, gbp | | ### Policies - **instant_is_domestic** (checks `speed`, `currency`): instant payouts support usd only ### Outputs | Field | Type | Required | Constraints | Description | |-------|------|----------|-------------|-------------| | `payout_id` | string | yes | | |
source
# frozen_string_literal: true # The API Reference Generator: walk the registry, emit reference docs # for every capability - types, enums, bounds, policies - straight from # the contracts that VALIDATE the calls. Documentation that enforces # itself cannot lie about what it accepts. # # bundle exec ruby examples/api_reference.rb # # Runs offline; prints markdown. require class="s">"bundler/setup" require class="s">"agentic" registry = Agentic:class="y">:AgentCapabilityRegistry.instance # Two capabilities as the "app": a transfer and a payout transfer = Agentic:class="y">:CapabilitySpecification.new( name: class="s">"transfer_funds", description: class="s">"Move money between accounts", version: class="s">"1.2.0", inputs: { from_account: {type: class="s">"string", required: true, non_empty: true, description: class="s">"Source account id"}, to_account: {type: class="s">"string", required: true, non_empty: true, description: class="s">"Destination account id"}, amount_cents: {type: class="s">"number", required: true, min: 1, max: 10_000_000, description: class="s">"Amount in cents"}, memo: {type: class="s">"string", description: class="s">"Optional statement memo"} }, outputs: { transfer_id: {type: class="s">"string", required: true}, settled: {type: class="s">"boolean", required: true} }, rules: { no_self_transfer: { message: class="s">"source and destination must differ", fields: [class="y">:from_account, class="y">:to_account], check: ->(i) { i[class="y">:from_account] != i[class="y">:to_account] } } } ) payout = Agentic:class="y">:CapabilitySpecification.new( name: class="s">"schedule_payout", description: class="s">"Schedule a payout to a bank account", version: class="s">"2.0.0", inputs: { amount_cents: {type: class="s">"number", required: true, min: 100}, speed: {type: class="s">"string", required: true, enum: %w[standard instant]}, currency: {type: class="s">"string", required: true, enum: %w[usd eur gbp]} }, outputs: {payout_id: {type: class="s">"string", required: true}}, rules: { instant_is_domestic: { message: class="s">"instant payouts support usd only", fields: [class="y">:speed, class="y">:currency], check: ->(i) { i[class="y">:speed] != class="s">"instant" || i[class="y">:currency] == class="s">"usd" } } } ) [transfer, payout].each do |spec| Agentic.register_capability(spec, Agentic:class="y">:CapabilityProvider.new( capability: spec, implementation: ->(_i) { {} } )) end # --- the generator: registry in, markdown out -------------------------------- def constraint_notes(declaration) notes = [] notes << class="s">"one of: #{declaration[class="y">:enum].join(", class="s">")}" if declaration[class="y">:enum] notes << class="s">">= #{declaration[class="y">:min]}" if declaration[class="y">:min] notes << class="s">"<= #{declaration[class="y">:max]}" if declaration[class="y">:max] notes << class="s">"non-empty" if declaration[class="y">:non_empty] notes.join(class="s">"; ") end def field_table(declared) rows = declared.map { |name, decl| required = decl[class="y">:required] ? class="s">"yes" : class="s">"no" format(class="s">"| `%s` | %s | %s | %s | %s |", name, decl[class="y">:type], required, constraint_notes(decl), decl[class="y">:description] || class="s">"") } [class="s">"| Field | Type | Required | Constraints | Description |", class="s">"|-------|------|----------|-------------|-------------|"] + rows end def reference_for(spec) doc = [class="s">"## `#{spec.name}` v#{spec.version}", class="s">"", spec.description, class="s">""] doc << class="s">"### Inputs" doc += field_table(spec.inputs) unless spec.rules.empty? doc << class="s">"" doc << class="s">"### Policies" spec.rules.each do |rule_id, rule| doc << class="s">"- **#{rule_id}** (checks #{rule[class="y">:fields].map { |f| "`#{f}`class="s">" }.join(", class="s">")}): #{rule[class="y">:message]}" end end unless spec.outputs.empty? doc << class="s">"" doc << class="s">"### Outputs" doc += field_table(spec.outputs) end doc.join(class="s">"\n") end puts class="s">"# API Reference" puts puts class="s">"_Generated from the same contracts that validate every call._" puts %w[transfer_funds schedule_payout].each do |name| puts reference_for(registry.get(name)) puts end