Draft 0.1

Open Financial Agent Protocol, draft 0.1

View as Markdown
Pages and sections
  1. 1. Overview
  2. 1.1 Roles
  3. 2. Conventions
  4. 3. Discovery
  5. 4. Conformance levels
  6. 5. Tools
  7. 6. Distributor
  8. 7. Products and documents
  9. 8. Question sets
  10. 8.1 Line profiles
  11. 9. Quote
  12. 10. Applications
  13. 11. Evidence
  14. 12. Agreements
  15. 13. Errors
  16. 14. Sector modules
  17. 15. Insurance module
  18. 16. Security and privacy
  19. 17. Checks
  20. 18. Open points

Draft 0.1 covers insurance. A later draft can break this one until 1.0. The source of truth is schema.ts, and the schema reference is generated from it. When this page and schema.ts differ, schema.ts wins.

1.Overview

OFAP defines how an AI agent finds, prices, subscribes to and services a regulated financial product with any distributor. It also defines the evidence that each step leaves, so that a sale through an agent meets the same rules as a sale on the distributor's own site.

OFAP is an extension on top of two protocols:

  • MCP carries every call. Each OFAP primitive is an MCP tool. A tool puts its result in structuredContent, with a short plain-text summary in content.
  • PAP carries the customer's session and every action with a business effect, through its operations extension. OFAP defines only the financial terms of those operations.

The protocol has a core that does not depend on the sector, and one module per sector. A module adds the pricing, the needs assessment and the documents that the law of its sector asks for. Draft 0.1 defines the insurance module. Sector modules gives the rules for a later one, for example credit or investment.

1.1Roles

  • Agent. The AI agent that acts for the customer. It calls the tools.
  • Distributor. The company that runs the MCP server and sells the product: an insurer, a broker, a tied agent, an MGA or a comparator.
  • Provider. The party that carries the risk. In insurance, the insurer. It can be the distributor itself.
  • Customer. The person or organisation that buys. Every commitment needs their approval through PAP.

2.Conventions

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" are to be read as described in BCP 14 (RFC 2119, RFC 8174) when, and only when, they appear in all capitals.

  • An amount is a Money object. Its amount is a decimal string such as "14.90", so that no value is lost to floating point.
  • Dates and times are ISO 8601. Countries are ISO 3166-1 alpha-2 codes, currencies ISO 4217 codes, and languages BCP 47 tags.
  • A hash is a lower-case hex SHA-256. The hash of a JSON value is the SHA-256 of its canonical JSON (RFC 8785).

3.Discovery

A server declares OFAP under capabilities.extensions["org.openfinancialagent/ofap"] in its MCP server/discover response, and under the same key in the extensions field of its PAP poppy.json. The value is an OfapSettings object: the protocol version, the conformance level, the sector modules, the product lines and the countries the server covers, and whether it can conclude an agreement inside the agent.

4.Conformance levels

Level Adds the tools Session (PAP)
1. Inform get_distributor, list_products, get_documents None
2. Quote get_question_set, quote None; None, or signed out
3. Subscribe submit_application, conclude None, or signed out
4. Service get_agreement, amend_agreement Signed in, read scope; Signed in, write scope

A server that declares a level MUST implement every tool of that level and of the levels below it. Level 3 needs only one of submit_application and conclude. A call to a tool above the declared level returns the error not_supported.

5.Tools

Tool Level Session (PAP) Effect Params → result
get_distributor 1 None Read-only GetDistributorParams → GetDistributorResult
list_products 1 None Read-only ListProductsParams → ListProductsResult
get_documents 1 None Read-only GetDocumentsParams → GetDocumentsResult
get_question_set 2 None Read-only GetQuestionSetParams → GetQuestionSetResult
quote 2 None, or signed out Read-only QuoteParams → QuoteResult
submit_application 3 None, or signed out Returns a PAP operation SubmitApplicationParams → SubmitApplicationResult
conclude 3 None, or signed out Returns a PAP operation ConcludeParams → ConcludeResult
get_agreement 4 Signed in, read scope Read-only GetAgreementParams → GetAgreementResult
amend_agreement 4 Signed in, write scope Returns a PAP operation AmendAgreementParams → AmendAgreementResult

The session column follows PAP draft 0.2. A read-only tool sets the MCP readOnlyHint annotation. The tools that return an operation commit nothing on their own: see Applications.

6.Distributor

get_distributor returns who sells, and under which licences. Its domain MUST match the server's own domain. Each Licence names the country, the regulator, the public register and the identifier, the role, and the sectors it covers. A licence can apply to subdivisions only, for example some US states. verification_url is the public page where anyone can check the entry, and complaints_url is where a customer can complain.

7.Products and documents

list_products returns Product objects, filtered by country, sector or line. Each product lists its subscription paths:

  • conclude: the agent concludes the agreement with conclude.
  • application: the agent sends submit_application, and the customer finishes on the distributor's page.
  • handoff: the customer goes to the distributor's page with an offer reference.

get_documents returns the FinancialDocument objects of a product, an offer or an agreement. Each document has a version, set by the distributor, and the SHA-256 of the exact file at its url. A new text MUST get a new version. required_before_commitment is true when the law requires that the customer receives the document before they commit, for example the IPID.

8.Question sets

get_question_set returns the questions of a product as a JSON Schema (2020-12) object, answers_schema. Each property is one question. OFAP adds three keywords to a property:

Keyword Meaning
x-collected-by agent, the default, or distributor_page
x-profile-key The key of the matching question in the line profile
x-ask A short question the agent can ask the customer, in plain words

A value marked distributor_page MUST NOT pass through the agent. The customer gives it on the distributor's own page. Use it for identity numbers, bank account and card numbers, tax numbers, health details and passwords. A server that gets such a value anyway stores nothing and returns sensitive_field_received.

A change in any question MUST change the version of the question set. Answers to an old version get question_set_outdated.

8.1Line profiles

A line profile is the common core of questions for one product line. A question set MUST include every required core question of its line, with the same key, and MAY add its own questions. Two products of the same line can then be quoted from the same answers. A profile needs a second distributor of the same line before it is stable.

insurance/pet@0.1

Derived from: pet insurer, FR, DE, SE.

Key Type Required Question or note
country string Yes In which country do you live?
postal_code string Yes What is your postal code?
municipality_code string Official municipality code, where the tariff uses it (for example in Sweden).
species dog, cat Yes Is it a dog or a cat?
pet_name string Yes What is your pet's name?
breed string Yes What breed is it?
is_mixed_breed boolean
mixed_breed_size small, medium, large, giant Dogs of mixed breed with unknown parents only.
sex female, male Yes
is_neutered boolean Yes Is your pet neutered or spayed?
date_of_birth string (date) Yes When was your pet born? An approximate date is fine.
lifestyle indoor, outdoor Cats only. Do not set for dogs.

insurance/home@0.1

Derived from: home insurer, ES.

Key Type Required Question or note
country string Yes In which country do you live?
street string Yes What is the street and number of the property?
city string Yes
postal_code string Yes What is the postal code?
usage tenant, owner_occupied, landlord, second_home Yes Do you rent it, live in it as the owner, rent it out, or use it as a second home?
floor_area_m2 number Yes How many square metres is the property?
property_type house, apartment Not asked by the source server today. Most home tariffs need it.

9.Quote

quote takes a product, a question set reference and the answers. The agent MAY send partial answers. The result has one of three states:

  • needs_input: missing_fields lists the questions that are missing, not valid or not accepted. The agent asks the customer and calls quote again with more answers.
  • in_progress: the agent reads the quote again after retry_after_seconds, and sends only the quote_request_id.
  • complete: offers lists the priced offers, and answers_sha256 is the hash of the answers used. When offers is empty, no_offer is REQUIRED. It gives a stable reason_code, such as age_not_accepted, and a message the agent can pass to the customer.

This one loop replaces the multi-step flow tools (action, stateUpdates, sessionId) that most servers use.

An Offer holds the provider, the pricing in the form of its sector, the last moment it can be accepted (valid_until), and its subscription paths. When indicative is true, the price can change after checks. An offer with the handoff path MUST have a handoff_url, and that URL MUST NOT contain personal data.

10.Applications

submit_application and conclude return a PAP operation in structuredContent.operation. The agent confirms it at the PAP operations endpoint, never through an OFAP tool. PAP is the authority for every field of the operation except terms and ofap_progress. When the two differ, PAP wins.

The terms of an application are an ApplicationTerms object. They hold every field the law needs as evidence, so that a confirmed revision records exactly what the customer accepted:

  • the offer, the provider, the pricing and the options;
  • the parties, each with its roles, for example subscriber, insured, beneficiary or payer;
  • the declaration: the answers, the question set version, their answers_sha256, and accuracy_confirmed;
  • the needs assessment, which MUST be of the same sector as the offer;
  • the documents delivered before this revision, each with its version and hash;
  • the contact consent, and the withdrawal period when the law gives one.

Every document of the offer with required_before_commitment: true MUST be in documents_delivered. Otherwise the server returns documents_not_delivered.

accuracy_confirmed is true only when the customer confirmed that the answers are true and complete. The agent MUST NOT set it to true for invented or test data.

A conclude operation MUST have user_approval_required: true, so a standing permission is not enough. Only the latest revision of an operation can be confirmed, and the revision increases when the terms change. While an operation is in_progress, ofap_progress can say why: a licensed person reviews the application, the provider decides, the customer must act on the distributor's page, or a payment is pending.

When the operation succeeds, result.data holds an ApplicationOutcome for an application, with the page where the customer finishes, or a ConcludeOutcome for a conclusion, with the agreement number and its documents. Both carry the evidence record.

11.Evidence

When an operation succeeds, the distributor keeps an EvidenceRecord. It links the exact revision the customer accepted to the documents delivered, the declaration, the needs assessment and the consent. Its terms_sha256 is the hash of the confirmed terms. The distributor MUST keep the record for the period the law requires.

A PAP confirmation proves that an agent stated the customer approved a revision. It does not prove that the customer saw the terms. The evidence record adds what was delivered and what was declared. It still does not prove that the customer read the documents.

12.Agreements

get_agreement returns an Agreement. It needs a signed-in PAP session with read scope. amend_agreement needs write scope. It takes a list of AmendmentChange values and returns a PAP operation whose terms are an AmendmentTerms object: the changes, the effective date, the pricing before and after, and the amount the customer pays at once, if any.

The operation MUST have user_approval_required: true when the price changes, when amount_due_now is set, or when a change adds or removes a party or a subject. A standing permission is not enough for these. A change that adds a party or a subject that the provider must price needs a declaration.

13.Errors

A tool returns an error in an MCP tool result with isError: true, as an OfapError in structuredContent.error. PAP errors such as insufficient_scope, sign_in_required and terms_changed keep their PAP form.

Code Meaning
not_licensed The distributor holds no licence for this country, subdivision, sector or line.
not_available_in_region The product is not sold where the customer is.
product_not_found No product has this product_id.
offer_not_found No offer has this offer_id.
offer_expired The offer is past its valid_until.
question_set_outdated The answers follow an old version of the question set.
sensitive_field_received A value marked distributor_page was sent through the agent. Nothing was stored.
documents_not_delivered A document with required_before_commitment is not in documents_delivered.
accuracy_not_confirmed The declaration does not have accuracy_confirmed: true.
needs_assessment_invalid The needs assessment is missing, of another sector, or its outcome does not allow the application.
agreement_not_found No agreement has this agreement_number.
amendment_not_allowed The provider does not accept this change to the agreement.
not_supported The tool is above the conformance level the server declares.

14.Sector modules

The core is the same for every sector. A sector module adds what the law of its sector asks for. A module MUST define:

A module MUST NOT change a core type or a core rule. The tools, the quote loop, the declaration, the PAP operations and the evidence record stay the same for every sector. A server declares the modules it implements in OfapSettings.sectors. An agent MUST NOT show a product, an offer or an agreement of a sector it does not implement as if it were of a known sector.

Candidate modules for a later draft:

  • Credit. SECCI and ESIS before commitment, creditworthiness under the CCD and the MCD, APR and total cost of credit.
  • Investment. KID under PRIIPs, suitability or appropriateness under MiFID II, fees and risk indicator.

15.Insurance module

  • Pricing. An InsurancePricing object: the Premium (amount, period, and whether taxes are in it), the same price for other periods, the cover summary, the options and the start date. The CoverSummary lists what is included, the limits and reimbursement rates, the excess, the main exclusions and the waiting period.
  • Needs assessment. An InsuranceNeedsAssessment records the customer's demands and needs before the contract is concluded (IDD Art. 20(1)). When the distributor gave a personal recommendation, advice_rationale is REQUIRED and says why the offer meets the need.
  • Documents. The IPID, the general and special conditions, the statement of demands and needs, and the proof of insurance.
  • Parties. The insured and the beneficiary, next to the subscriber and the payer of the core.
  • Amendments. A change of excess, and the addition or removal of a subject, such as a pet, a home or a vehicle.
  • Registers. ORIAS in France, the FCA register in the United Kingdom, NIPR in the United States and the DGSFP register in Spain.

16.Security and privacy

  • Values marked distributor_page never pass through the agent.
  • Data in a Party MUST be limited to what the product needs. Identity numbers MUST NOT be in a party.
  • A handoff_url MUST NOT contain personal data.
  • Every commitment goes through a PAP operation, and the evidence record keeps the hash of the terms the customer approved.

Report a weakness that could harm a live implementation privately, as SECURITY.md describes.

17.Checks

The repository builds a worked pet insurance flow and checks it against schema.json and against the rules that a JSON Schema cannot express:

  • R1 profiles compile.
  • R2 a question set has every required question of its profile.
  • R3 answers match their question set.
  • R4 no distributor_page field in agent answers.
  • R5 answers_sha256 is the SHA-256 of the canonical JSON (RFC 8785).
  • R6 every document required before commitment was delivered, same version and digest.
  • R7 accuracy confirmed before a proposal.
  • R8 needs assessment and pricing match the offer's sector.
  • R9 an application needs the customer's own approval.
  • R10 a non-life insurance product has an IPID required before commitment.
  • R11 the evidence hash matches the confirmed terms.
  • R12 a price change, an amount due, or a change of party or subject needs the customer's own approval.
  • R13 a handoff offer has a handoff_url.
  • R14 an empty quote gives a reason.

18.Open points

  1. Conversation-only distributors. ConversationData is a proposal. Decide whether a distributor that exposes only a company agent can reach level 2 if it returns structured quotes.
  2. PAP fields. Operation mirrors PAP draft 0.2 and rejects unknown fields. It must accept new PAP fields before 1.0.
  3. Credit and investment modules. Draft each one on the rules for sector modules (section 8 of schema.ts), with at least two distributors as input.
  4. Profiles. A second distributor for the pet and home profiles, and profiles for commercial lines.
  5. Legal review of the IDD references, country by country.
  6. Governance. FINOS (Linux Foundation) is a candidate home, next to MCP and A2A.

To give feedback, open an issue.