Draft 0.1
Schema reference, draft 0.1
Pages and sections
- 1. Identity of the extension
- 2. Common types
- 3. Distributor (level 1)
- 4. Products (level 1)
- 5. Documents (level 1)
- 6. Question sets (level 2)
- 7. Quote (level 2)
- 8. Validation of the answers (level 2)
- 9. Premium and cover
- 10. Parties, needs and consent
- 11. PAP operations and applications (level 3)
- 12. Evidence
- 13. Errors
- 14. Conversation binding (PROPOSED, NOT DECIDED)
- 15. Tool index
- R1. Registry server
- R2. Common types
- R3. Listing
- R4. Search
- R5. Licence check
- R6. Country rules
- R7. Errors
- R8. Tool index
Every type of AIP draft 0.1, generated from schema.ts and registry.ts through schema.json. The sections follow schema.ts, then registry.ts from R1. The rules in the descriptions use the RFC 2119 keywords.
1.Identity of the extension
ConformanceLevel
Conformance level that a distributor declares.
- 1 Inform:
get_distributor,list_products,get_documents - 2 Quote: level 1, plus
get_question_set,quoteandvalidate_answers - 3 Subscribe: level 2, plus
submit_applicationorconclude
A server that declares a level MUST implement every tool of that level and of the levels below it, except that level 3 needs only one of submit_application and conclude. A server at level 2 can give binding offers, because it implements validate_answers.
Type: one of 1, 2, 3.
InterfaceKind
How a distributor exposes the protocol.
Type: one of tools, conversation.
AipSettings
Settings object of the extension. A server puts it under capabilities.extensions["org.agenticinsuranceprotocol/aip"] in its MCP server/discover response, and under the same key in the extensions field of its PAP poppy.json.
| Field | Type | Required | Description |
|---|---|---|---|
version |
string | Yes | Protocol version the server implements. |
conformance_level |
ConformanceLevel |
Yes | |
interfaces |
list of InterfaceKind |
Yes | |
lines |
list of ProductLine |
Yes | Product lines the server can quote. |
countries |
list of CountryCode |
Yes | Countries where the server's products are sold. |
can_conclude |
boolean | Yes | True when the server can conclude an agreement inside the agent (conclude). False when the customer always finishes on the distributor's own page. |
2.Common types
CountryCode
ISO 3166-1 alpha-2 country code, upper case.
Type: string. Pattern: ^[A-Z]{2}$.
SubdivisionCode
ISO 3166-2 subdivision code, upper case, for example "US-CA" for California.
Type: string. Pattern: ^[A-Z]{2}-[A-Z0-9]{1,3}$.
CurrencyCode
ISO 4217 currency code.
Type: string. Pattern: ^[A-Z]{3}$.
Lei
Legal Entity Identifier (ISO 17442): 18 letters or digits, then 2 check digits.
Type: string. Pattern: ^[A-Z0-9]{18}[0-9]{2}$.
LanguageTag
BCP 47 language tag, for example fr or es-ES.
Type: string. Pattern: ^[a-zA-Z]{2,3}(-[a-zA-Z0-9]{2,8})*$.
DateString
Calendar date, ISO 8601.
Type: string (date).
DateTimeString
Date and time with offset, ISO 8601.
Type: string (date-time).
Url
Type: string (uri).
Sha256
Lower-case hex SHA-256 digest.
Type: string. Pattern: ^[a-f0-9]{64}$.
Decimal
A decimal number as a string, so that no value is lost to floating point, for example "12.90".
Type: string. Pattern: ^-?[0-9]+(\.[0-9]+)?$.
Money
| Field | Type | Required | Description |
|---|---|---|---|
amount |
Decimal |
Yes | |
currency |
CurrencyCode |
Yes |
ProductLine
Product line. Servers SHOULD use a value of KnownProductLine. Other values MUST be lower case with underscores.
Type: string. Pattern: ^[a-z][a-z0-9_]*$.
KnownProductLine
Lines that have, or will have, a profile in AIP.
Type: one of pet, home, renters, motor, travel, health, life, funeral, borrower_insurance, professional_liability, general_liability, business_owners_policy, workers_compensation.
InsuredFamily
Family of what a product insures: a kind of person, or a kind of good. Servers SHOULD use a value of KnownInsuredFamily. Other values MUST be lower case with underscores.
Type: string. Pattern: ^[a-z][a-z0-9_]*$.
KnownInsuredFamily
Families that the known product lines need.
Type: one of person, organisation, pet, dwelling, contents, vehicle.
3.Distributor (level 1)
DistributorRole
Role of a party in the distribution chain. The provider roles are in ProviderRole.
Type: ProviderRole or broker or agent or mga or comparator.
RegisterIdentifierType
Kind of public register identifier.
Type: one of orias_number, siren, fca_frn, npn, dgsfp_key, naic_cocode, lei, other.
Licence
One entry in a public register that gives the right to sell a product, or to carry its risk.
| Field | Type | Required | Description |
|---|---|---|---|
country |
CountryCode |
Yes | |
regulator |
string | Yes | Supervising authority, for example "ACPR", "FCA", "DGSFP". |
register |
string | Yes | Name of the public register, for example "ORIAS", "REGAFI", "FCA Register", "NIPR". |
identifier_type |
RegisterIdentifierType |
Yes | |
identifier |
string | Yes | |
role |
DistributorRole |
Yes | |
categories |
list of string | Register categories, for example ORIAS "COA" (insurance broker) or "AGA" (tied insurance agent). | |
subdivisions |
list of SubdivisionCode |
Subdivisions where the licence applies, for example US states as ISO 3166-2 codes ("US-CA"). Omit when the licence covers the whole country. | |
verification_url |
Url |
Public page where anyone can check the entry. |
GetDistributorParams
Params of get_distributor. No params.
Type: object.
GetDistributorResult
| Field | Type | Required | Description |
|---|---|---|---|
legal_name |
string | Yes | |
trading_name |
string | ||
domain |
string | Yes | Domain the distributor controls. It MUST match the server's own domain. |
lei |
Lei |
Legal Entity Identifier, when the distributor has one. The registry uses it to match one company across registers. | |
roles |
list of DistributorRole |
Yes | |
licences |
list of Licence |
Yes | Every licence the distributor relies on to sell the listed products. |
countries |
list of CountryCode |
Yes | |
complaints_url |
Url |
Where a customer can complain. Required by most regulators. | |
aip |
AipSettings |
Yes | Settings the server declares for AIP. |
4.Products (level 1)
ProviderRole
Role of the party that carries the risk.
Type: insurer.
ProviderRef
The party that carries the risk.
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | |
legal_name |
string | ||
role |
ProviderRole |
Yes | |
domain |
string | Domain the provider controls, so that an agent can find it in the registry. | |
lei |
Lei |
Legal Entity Identifier, when the provider has one. | |
licences |
list of Licence |
Yes | The register entries that allow the provider to carry the risk, for example its authorisation as an insurer. At least one. |
SubscriptionPath
How a customer can subscribe to a product.
Type: one of conclude, application, handoff.
Product
| Field | Type | Required | Description |
|---|---|---|---|
product_id |
string | Yes | |
name |
string | Yes | |
line |
ProductLine |
Yes | |
provider |
ProviderRef |
Provider of the product, when it is not the distributor. | |
underwriting_scope |
UnderwritingScope |
Yes | The risks the product can cover. A product MUST publish it. |
summary |
string | Yes | |
details |
ProductDetails |
Yes | |
subscription_paths |
list of SubscriptionPath |
Yes |
UnderwritingScope
The risks a product can cover. list_products gives it with no customer data, so that an agent can drop a product that cannot cover the customer before it asks a question.
geography and insured are the structured part, which a machine can check against the answers. A server MUST NOT return an offer for a risk outside the structured part. An agent MUST NOT send answers to quote for a product whose structured part excludes the customer. conditions holds the rest.
| Field | Type | Required | Description |
|---|---|---|---|
version |
string | Yes | Version of the scope. A change in any part MUST change it. |
geography |
Geography |
Yes | |
insured |
list of InsuredType |
Yes | What the product insures. At least one. |
conditions |
list of string | Yes | The conditions that a machine cannot check, in plain words, for example "Houses built after 1950 only" or "Not for people over 70". Empty when there are none. An agent SHOULD check them against what the customer said before it quotes, and ask the customer when it is not sure. |
Geography
Where the insured person lives, or where the insured good is.
| Field | Type | Required | Description |
|---|---|---|---|
countries |
list of CountryCode |
Yes | Countries the product covers. At least one. |
subdivisions |
list of SubdivisionCode |
Subdivisions the product covers, for example US states. Each one MUST belong to a country in countries. The product covers the whole of each country that has no subdivision in this list. |
InsuredType
A family of insured, and the kinds of it that a product covers.
| Field | Type | Required | Description |
|---|---|---|---|
family |
InsuredFamily |
Yes | |
kinds |
list of string | Kinds that the product covers, for example "cat" and "dog". Omit when it covers every kind. When the line profile names a kind_key for this family, each kind MUST be a value that this question accepts. |
ProductDetails
What the product covers, and the options a customer can add.
| Field | Type | Required | Description |
|---|---|---|---|
cover |
CoverSummary |
Yes | |
options |
list of ProductOption |
ListProductsParams
Params of list_products. Each filter is optional. The server MUST return only the products whose line and underwriting scope match every filter given.
| Field | Type | Required | Description |
|---|---|---|---|
country |
CountryCode |
||
subdivision |
SubdivisionCode |
Products that cover this subdivision. | |
line |
ProductLine |
||
insured_family |
InsuredFamily |
Products that insure this family. | |
cursor |
string |
ListProductsResult
| Field | Type | Required | Description |
|---|---|---|---|
products |
list of Product |
Yes | |
next_cursor |
string |
5.Documents (level 1)
DocumentType
Kind of document.
Type: one of pre_contract_information, terms_of_business, other, ipid, general_conditions, special_conditions, demands_and_needs, proof_of_insurance.
InsuranceDocument
| Field | Type | Required | Description |
|---|---|---|---|
document_id |
string | Yes | |
type |
DocumentType |
Yes | |
title |
string | Yes | |
language |
LanguageTag |
Yes | |
version |
string | Yes | Version label set by the distributor. A new text MUST get a new version. |
url |
Url |
Yes | |
media_type |
string | Yes | |
sha256 |
Sha256 |
Yes | Digest of the exact file at url. Used as evidence of what was delivered. |
required_before_commitment |
boolean | Yes | True when the law requires that the customer receives this document before they commit, for example the IPID. |
GetDocumentsParams
Params of get_documents. Give exactly one of the two references.
Variant 1
| Field | Type | Required | Description |
|---|---|---|---|
product_id |
string | Yes | |
country |
CountryCode |
||
language |
LanguageTag |
Variant 2
| Field | Type | Required | Description |
|---|---|---|---|
offer_id |
string | Yes | |
language |
LanguageTag |
GetDocumentsResult
| Field | Type | Required | Description |
|---|---|---|---|
documents |
list of InsuranceDocument |
Yes |
6.Question sets (level 2)
CollectedBy
Who collects the value of a question.
agent: the agent MAY ask and send the value.distributor_page: the value 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.
Type: one of agent, distributor_page.
AnswersSchema
A JSON Schema (2020-12) object that describes the answers. Each property is one question. AIP adds these keywords to each property:
x-collected-by: aCollectedByvalue. Defaultagent.x-profile-key: the key of the matching question in the line profile, when the question is part of the common core.x-ask: a short question the agent can ask the customer, in plain words.
| Field | Type | Required | Description |
|---|---|---|---|
type |
object |
Yes | |
properties |
map of map of any | Yes | |
required |
list of string |
QuestionSet
| Field | Type | Required | Description |
|---|---|---|---|
question_set_id |
string | Yes | |
version |
string | Yes | Version of this question set. A change in any question MUST change it. |
product_id |
string | Yes | |
line |
ProductLine |
Yes | |
profile |
string | Line profile and version this question set builds on, for example "pet@0.1". | |
answers_schema |
AnswersSchema |
Yes |
GetQuestionSetParams
| Field | Type | Required | Description |
|---|---|---|---|
product_id |
string | Yes | |
country |
CountryCode |
GetQuestionSetResult
| Field | Type | Required | Description |
|---|---|---|---|
question_set |
QuestionSet |
Yes |
QuestionSetRef
| Field | Type | Required | Description |
|---|---|---|---|
question_set_id |
string | Yes | |
version |
string | Yes |
Answers
Answers keyed by property name in answers_schema.
Type: map of any.
AnswerOrigin
Who produced the value of an answer.
Type: one of customer, agent, third_party.
AnswerSource
Where one answer comes from. validated_by_customer is true when the customer confirmed this value before the agent sent it. It is always true when the customer gave the value. An agent MUST NOT set validated_by_customer to true when the customer did not validate that answer.
origin: customer
| Field | Type | Required | Description |
|---|---|---|---|
origin |
customer |
Yes | |
validated_by_customer |
true |
Yes |
origin: agent
| Field | Type | Required | Description |
|---|---|---|---|
origin |
agent |
Yes | |
validated_by_customer |
boolean | Yes |
origin: third_party
| Field | Type | Required | Description |
|---|---|---|---|
origin |
third_party |
Yes | |
validated_by_customer |
boolean | Yes | |
source_name |
string | Yes | The third party, by its kind and country, for example "vehicle register (FR)". |
AnswerSources
The source of each answer, keyed like answers. An agent MUST give a source for each answer, and no source for a key that has no answer. Otherwise the server returns answers_invalid.
Type: map of AnswerSource.
7.Quote (level 2)
QuoteParams
Params of quote.
The agent MAY send partial answers. The server then returns needs_input with the missing fields, and the agent calls quote again with more answers. This one loop replaces the multi-step flow tools (action, stateUpdates, sessionId) that most servers use. Some servers already work this way.
Without validation, every offer is indicative. To get binding offers, the agent first has the customer validate the answers with validate_answers, then sends the same answers and sources with that validation.
To read a quote that is still in progress, send only quote_request_id.
Variant 1
| Field | Type | Required | Description |
|---|---|---|---|
product_id |
string | Yes | |
question_set |
QuestionSetRef |
Yes | |
answers |
Answers |
Yes | |
answer_sources |
AnswerSources |
Yes | Where each answer comes from, keyed like answers. |
validation |
AnswersValidation |
The customer's validation of these answers and sources, from a succeeded validate_answers operation. When it does not match them, the server returns answers_not_validated. |
|
options |
list of string | Options the customer wants priced, by key (optional covers, extra services). | |
language |
LanguageTag |
Variant 2
| Field | Type | Required | Description |
|---|---|---|---|
quote_request_id |
string | Yes |
Offer
One priced offer. A distributor can return several offers: one per tier, per provider, or per duration.
When a server implements quote, an agent MUST take the price, the cover, the limits and the excess that it shows the customer from the offer, and MUST NOT take them from a page made for people.
| Field | Type | Required | Description |
|---|---|---|---|
offer_id |
string | Yes | |
product_id |
string | Yes | |
tier |
string | Name of the tier or plan, for example "Terceros Ampliado" or "Band B". | |
provider |
ProviderRef |
Yes | |
underwriting_scope_version |
string | Yes | Version of the product's underwriting scope that the server applied. |
pricing |
Pricing |
Yes | The price and the cover. A binding offer MUST give cover.excess and cover.limits. An empty limits means that the cover has no limit. |
indicative |
boolean | Yes | True when the offer is indicative and can change after checks. False makes the offer binding. A server MUST NOT return a binding offer unless the quote carries the customer's validation of its answers and sources. |
valid_until |
DateTimeString |
Yes | Last moment the offer can be accepted at this price. |
subscription_paths |
list of SubscriptionPath |
Yes | |
handoff_url |
Url |
Page where the customer can continue with this exact offer. Required when subscription_paths contains handoff. It MUST NOT contain personal data. |
|
recommended |
boolean | True when the distributor recommends this offer after advice. |
QuoteResult
status: complete
| Field | Type | Required | Description |
|---|---|---|---|
status |
complete |
Yes | |
quote_request_id |
string | Yes | |
question_set |
QuestionSetRef |
Yes | |
answers_sha256 |
Sha256 |
Yes | SHA-256 of the canonical JSON (RFC 8785) of the answers used. |
answer_sources_sha256 |
Sha256 |
Yes | SHA-256 of the canonical JSON (RFC 8785) of the answer sources used. |
validation |
AnswersValidation |
The validation the server applied. Required when an offer is binding. | |
offers |
list of Offer |
Yes | |
no_offer |
NoOffer |
Required when offers is empty. |
status: needs_input
| Field | Type | Required | Description |
|---|---|---|---|
status |
needs_input |
Yes | |
quote_request_id |
string | Yes | |
missing_fields |
list of FieldIssue |
Yes | Properties of answers_schema that are missing or not valid. |
status: in_progress
| Field | Type | Required | Description |
|---|---|---|---|
status |
in_progress |
Yes | |
quote_request_id |
string | Yes | |
retry_after_seconds |
number | Yes | When the agent SHOULD read the quote again. |
message |
string | Plain-language status, for example "Two insurers have answered, three to go". |
NoOffer
Why no offer is possible.
| Field | Type | Required | Description |
|---|---|---|---|
reason_code |
NoOfferReason |
Yes | |
message |
string | Yes | Plain-language explanation the agent can pass to the customer. |
NoOfferReason
Stable reason why no offer is possible. Servers SHOULD use a value of KnownNoOfferReason. Other values MUST be lower case with underscores.
Type: string. Pattern: ^[a-z][a-z0-9_]*$.
KnownNoOfferReason
Common reason codes. outside_underwriting_scope means that the risk is outside the product's underwriting scope: its geography, its insured types or its conditions. A quote for a risk outside the structured part MUST get this reason.
Type: one of outside_underwriting_scope, risk_not_accepted, age_not_accepted, breed_not_accepted, claims_history_not_accepted.
8.Validation of the answers (level 2)
ValidateAnswersParams
Params of validate_answers. The agent calls it before it asks for binding offers, and before an application. The answers MUST be complete for the question set. Otherwise the server returns answers_invalid.
| Field | Type | Required | Description |
|---|---|---|---|
product_id |
string | Yes | |
question_set |
QuestionSetRef |
Yes | |
answers |
Answers |
Yes | |
answer_sources |
AnswerSources |
Yes | Where each answer comes from, keyed like answers. |
language |
LanguageTag |
Language of the operation summary. |
ValidationTerms
Terms of a validation: the answers that the customer validates, and their sources. The summary of the operation MUST show each answer and its source in plain words, so that the customer can check each one.
| Field | Type | Required | Description |
|---|---|---|---|
product_id |
string | Yes | |
question_set |
QuestionSetRef |
Yes | |
answers |
Answers |
Yes | |
answer_sources |
AnswerSources |
Yes | |
answers_sha256 |
Sha256 |
Yes | SHA-256 of the canonical JSON (RFC 8785) of answers. |
answer_sources_sha256 |
Sha256 |
Yes | SHA-256 of the canonical JSON (RFC 8785) of answer_sources. |
ValidateAnswersResult
Result of validate_answers. The operation MUST have user_approval_required: true, because only the customer can validate their answers. The agent MUST ask the person who will be the subscriber to approve it. When it succeeds, result.data holds a ValidationOutcome.
| Field | Type | Required | Description |
|---|---|---|---|
operation |
Operation<ValidationTerms> |
Yes |
ValidationOutcome
| Field | Type | Required | Description |
|---|---|---|---|
validation |
AnswersValidation |
Yes |
AnswersValidation
The record that the customer validated a set of answers and their sources: a succeeded validate_answers operation. The server keeps it. The agent copies it into quote to get binding offers, and into the declaration of an application.
| Field | Type | Required | Description |
|---|---|---|---|
operation_id |
string | Yes | |
revision |
number | Yes | |
validated_at |
DateTimeString |
Yes | When the customer approved the operation: its confirmation.confirmed_at. |
answers_sha256 |
Sha256 |
Yes | |
answer_sources_sha256 |
Sha256 |
Yes |
FieldIssue
| Field | Type | Required | Description |
|---|---|---|---|
field |
string | Yes | |
issue |
one of missing, invalid, not_accepted |
Yes | |
message |
string |
9.Premium and cover
PremiumPeriod
Type: one of month, quarter, half_year, year, single.
Premium
| Field | Type | Required | Description |
|---|---|---|---|
amount |
Money |
Yes | |
period |
PremiumPeriod |
Yes | |
taxes_included |
boolean | Yes | True when taxes and mandatory levies are in amount. |
CoverLimit
| Field | Type | Required | Description |
|---|---|---|---|
key |
string | Yes | Stable key, for example "vet_costs_per_year". |
label |
string | Yes | |
limit |
Money |
||
reimbursement_rate |
number | Share of a claim paid back, from 0 to 1. Used by pet and health cover. |
CoverSummary
| Field | Type | Required | Description |
|---|---|---|---|
included |
list of string | Yes | Covers included, as short labels. |
limits |
list of CoverLimit |
||
excess |
Money |
||
main_exclusions |
list of string | Main exclusions. The full list is in the documents. | |
waiting_period_days |
number |
ProductOption
An option the customer can add (optional cover, extra service).
| Field | Type | Required | Description |
|---|---|---|---|
key |
string | Yes | |
label |
string | Yes | |
price |
Premium or Money |
Cost of the option, in the same form as the main price. |
Pricing
The price of an offer, and the cover it buys.
| Field | Type | Required | Description |
|---|---|---|---|
premium |
Premium |
Yes | |
alternative_premiums |
list of Premium |
The same price for another period, when the server can give it. | |
cover |
CoverSummary |
Yes | |
options |
list of ProductOption |
||
start_date |
DateString |
10.Parties, needs and consent
PartyRole
Role of a party in the agreement.
Type: one of subscriber, payer, insured, beneficiary.
Party
A person or organisation in the agreement. Data in a party MUST be limited to what the product needs. Identity numbers MUST NOT be here (see CollectedBy).
| Field | Type | Required | Description |
|---|---|---|---|
party_ref |
string | Yes | Local reference, unique in one application. |
kind |
one of person, organisation |
Yes | |
roles |
list of PartyRole |
Yes | |
display_name |
string | Yes | |
relationship_to_subscriber |
string | Relationship to the subscriber, for example "self", "spouse", "child", "employee". | |
date_of_birth |
DateString |
||
country_of_residence |
CountryCode |
NeedsAssessment
Demands and needs, recorded before the contract is concluded (IDD Art. 20(1)).
| Field | Type | Required | Description |
|---|---|---|---|
kind |
demands_and_needs |
Yes | |
statement |
string | Yes | The need in the customer's words or a faithful summary. |
advice_given |
boolean | Yes | True when the distributor gave a personal recommendation (advice). |
advice_rationale |
string | Why the recommended offer meets the need. Required when advice_given is true. |
|
recorded_at |
DateTimeString |
Yes |
ContactConsent
The customer's choice about later contact.
| Field | Type | Required | Description |
|---|---|---|---|
channels |
list of one of email, phone, sms, post |
Yes | Channels the distributor MAY use to contact the customer. Empty means none. |
details_collected_by |
CollectedBy |
Yes | When distributor_page, the contact details never pass through the agent. |
providers_may_contact |
boolean | Yes | True only when the customer agreed that providers may contact them too. |
purposes |
list of string | Yes | Purposes the customer agreed to, for example "this_application", "marketing". |
DeliveredDocument
| Field | Type | Required | Description |
|---|---|---|---|
document_id |
string | Yes | |
version |
string | Yes | |
sha256 |
Sha256 |
Yes | |
delivered_at |
DateTimeString |
Yes |
Declaration
The answers the customer commits to, with their sources and the customer's validation.
| Field | Type | Required | Description |
|---|---|---|---|
question_set |
QuestionSetRef |
Yes | |
answers |
Answers |
Yes | |
answer_sources |
AnswerSources |
Yes | Where each answer comes from, keyed like answers. |
answers_sha256 |
Sha256 |
Yes | |
answer_sources_sha256 |
Sha256 |
Yes | |
accuracy_confirmed |
boolean | Yes | True when the customer confirmed that the answers are true and complete. The agent MUST NOT set it to true for invented or test data. |
validation |
AnswersValidation |
Yes | The customer's validation of these answers and sources. Its hashes MUST be answers_sha256 and answer_sources_sha256, and its operation MUST have succeeded. Otherwise the server returns answers_not_validated. |
11.PAP operations and applications (level 3)
OperationState
Type: one of proposed, in_progress, succeeded, failed, cancelled, expired.
Operation<ApplicationTerms>
A PAP operation. This mirrors the PAP operations extension (version 1). PAP is the authority for every field here except terms and aip_progress. When the two differ, PAP wins.
An MCP tool returns it in structuredContent.operation. The agent confirms it at the PAP operations endpoint, never through an AIP tool.
| Field | Type | Required | Description |
|---|---|---|---|
operation_id |
string | Yes | |
revision |
number | Yes | Starts at 1. Increases when the terms change. Only the latest revision can be confirmed. |
state |
OperationState |
Yes | |
summary |
string | Yes | Plain-language terms that the customer can decide from alone. |
terms |
ApplicationTerms |
Yes | |
expires_at |
DateTimeString |
Required while proposed. |
|
user_approval_required |
boolean | Yes | When true, a standing permission is not enough. The customer MUST approve this revision. |
url |
Url |
||
confirmation |
null or object with revision, approved_by, confirmed_at |
Yes | |
result |
null or object with summary, data |
Yes | |
aip_progress |
AipProgress |
AIP reason why the operation is in_progress. Not a PAP field. Clients that do not know AIP ignore it. |
Operation<ValidationTerms>
A PAP operation. This mirrors the PAP operations extension (version 1). PAP is the authority for every field here except terms and aip_progress. When the two differ, PAP wins.
An MCP tool returns it in structuredContent.operation. The agent confirms it at the PAP operations endpoint, never through an AIP tool.
| Field | Type | Required | Description |
|---|---|---|---|
operation_id |
string | Yes | |
revision |
number | Yes | Starts at 1. Increases when the terms change. Only the latest revision can be confirmed. |
state |
OperationState |
Yes | |
summary |
string | Yes | Plain-language terms that the customer can decide from alone. |
terms |
ValidationTerms |
Yes | |
expires_at |
DateTimeString |
Required while proposed. |
|
user_approval_required |
boolean | Yes | When true, a standing permission is not enough. The customer MUST approve this revision. |
url |
Url |
||
confirmation |
null or object with revision, approved_by, confirmed_at |
Yes | |
result |
null or object with summary, data |
Yes | |
aip_progress |
AipProgress |
AIP reason why the operation is in_progress. Not a PAP field. Clients that do not know AIP ignore it. |
AipProgress
| Field | Type | Required | Description |
|---|---|---|---|
reason |
one of licensed_review, provider_decision, customer_action_on_distributor_page, payment_pending |
Yes | |
url |
Url |
||
expected_by |
DateTimeString |
ApplicationTerms
Terms of an application or a conclusion. Every field the law needs as evidence is here, so that a confirmed revision records exactly what the customer accepted.
| Field | Type | Required | Description |
|---|---|---|---|
offer_id |
string | Yes | |
product_id |
string | Yes | |
provider |
ProviderRef |
Yes | |
pricing |
Pricing |
Yes | The pricing of the offer, unchanged. It MUST be the pricing that quote returned for offer_id. |
options |
list of string | Yes | |
start_date |
DateString |
||
parties |
list of Party |
Yes | |
declaration |
Declaration |
Yes | |
needs_assessment |
NeedsAssessment |
Yes | |
documents_delivered |
list of DeliveredDocument |
Yes | Documents delivered before this revision was proposed. Every document of the offer with required_before_commitment: true MUST be in this list. |
contact_consent |
ContactConsent |
Yes | |
withdrawal_period_days |
number | Days the customer has to withdraw after conclusion, when the law gives the right. |
SubmitApplicationParams
| Field | Type | Required | Description |
|---|---|---|---|
offer_id |
string | Yes | |
parties |
list of Party |
Yes | |
declaration |
Declaration |
Yes | |
needs_assessment |
NeedsAssessment |
Yes | |
documents_delivered |
list of DeliveredDocument |
Yes | |
contact_consent |
ContactConsent |
Yes | |
options |
list of string | ||
start_date |
DateString |
SubmitApplicationResult
When the operation succeeds, result.data holds an ApplicationOutcome.
| Field | Type | Required | Description |
|---|---|---|---|
operation |
Operation<ApplicationTerms> |
Yes |
ApplicationOutcome
| Field | Type | Required | Description |
|---|---|---|---|
application_id |
string | Yes | |
evidence |
EvidenceRecord |
Yes | |
handoff_url |
Url |
Yes | Page where the customer finishes the subscription. |
ConcludeParams
Type: SubmitApplicationParams.
ConcludeResult
Result of conclude. The operation MUST have user_approval_required: true. When it succeeds, result.data holds a ConcludeOutcome.
| Field | Type | Required | Description |
|---|---|---|---|
operation |
Operation<ApplicationTerms> |
Yes |
ConcludeOutcome
| Field | Type | Required | Description |
|---|---|---|---|
agreement_number |
string | Yes | |
evidence |
EvidenceRecord |
Yes | |
documents |
list of InsuranceDocument |
Yes |
12.Evidence
EvidenceRecord
What the distributor keeps when an operation succeeds. It links the exact revision the customer accepted to the documents, the declaration with its sources and its validation, the needs assessment, the consent and the underwriting scope. The distributor MUST keep it 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. This record adds what was delivered and what was declared. It still does not prove that the customer read the documents.
| Field | Type | Required | Description |
|---|---|---|---|
record_id |
string | Yes | |
operation_id |
string | Yes | |
revision |
number | Yes | |
approved_by |
one of user, standing_permission |
Yes | |
confirmed_at |
DateTimeString |
Yes | |
documents_delivered |
list of DeliveredDocument |
Yes | |
question_set |
QuestionSetRef |
Yes | |
answers_sha256 |
Sha256 |
Yes | |
answer_sources_sha256 |
Sha256 |
Yes | SHA-256 of the canonical JSON (RFC 8785) of the answer sources. The server MUST keep the sources with the declaration. |
validation |
AnswersValidation |
Yes | The customer's validation of the answers and their sources. |
underwriting_scope_version |
string | Yes | Version of the underwriting scope that the offer applied. |
needs_assessment |
NeedsAssessment |
Yes | |
contact_consent |
ContactConsent |
Yes | |
terms_sha256 |
Sha256 |
Yes | SHA-256 of the canonical JSON (RFC 8785) of the confirmed terms. |
13.Errors
AipErrorCode
Type: one of not_licensed, not_available_in_region, product_not_found, offer_not_found, offer_expired, question_set_outdated, sensitive_field_received, documents_not_delivered, answers_invalid, answers_not_validated, accuracy_not_confirmed, needs_assessment_invalid, not_supported.
AipError
Error returned in an MCP tool result with isError: true, in structuredContent.error. PAP errors (insufficient_scope, sign_in_required, terms_changed) keep their PAP form.
| Field | Type | Required | Description |
|---|---|---|---|
code |
AipErrorCode |
Yes | |
message |
string | Yes | |
fields |
list of FieldIssue |
14.Conversation binding (PROPOSED, NOT DECIDED)
ConversationData
PROPOSED. Some distributors expose only a company agent. If AIP accepts them at level 2, each message that carries an AIP object puts it here, in the message's structured data (data in a PAP conversation, structuredContent in a chat tool).
| Field | Type | Required | Description |
|---|---|---|---|
question |
object with field, ask, schema |
||
quote |
QuoteResult |
||
documents |
list of InsuranceDocument |
||
operation |
Operation<ApplicationTerms> |
15.Tool index
ToolName
Type: one of get_distributor, list_products, get_documents, get_question_set, quote, validate_answers, submit_application, conclude.
SessionRequirement
Session that a tool needs (PAP draft 0.2).
Type: one of none, signed_out_or_none.
ToolSignatures
Params and result type of each tool.
| Field | Type | Required | Description |
|---|---|---|---|
get_distributor |
object with params, result |
Yes | |
list_products |
object with params, result |
Yes | |
get_documents |
object with params, result |
Yes | |
get_question_set |
object with params, result |
Yes | |
quote |
object with params, result |
Yes | |
validate_answers |
object with params, result |
Yes | |
submit_application |
object with params, result |
Yes | |
conclude |
object with params, result |
Yes |
R1. Registry server
RegistrySettings
Settings object of the registry extension. The registry puts it under capabilities.extensions["org.agenticinsuranceprotocol/registry"] in its MCP server/discover response.
The registry SHOULD also serve the buyer skill through the MCP Skills extension (io.modelcontextprotocol/skills). An agent whose host loads skills over MCP then gets the whole skill from the registry, and get_country_rules serves the same country files to the other agents.
| Field | Type | Required | Description |
|---|---|---|---|
version |
string | Yes | Protocol version the registry implements. |
countries |
list of CountryCode |
Yes | Countries where the registry checks licences and lists servers. |
rules_countries |
list of CountryCode |
Yes | Countries that have a rules file in get_country_rules. |
sources |
list of RegisterSource |
Yes | Every public register the registry reads. |
policy_url |
Url |
Yes | Page where the operator publishes how it lists servers, how it checks licences, how it maps register categories to lines, and how to reach it. |
SourceAccess
How the registry reads a public register. The registry MUST read a register only through an access that the terms of the register allow, and under an agreement when the terms ask for one. Most registers forbid robots on their web pages.
Type: one of api, bulk_file, web_page.
RegisterCoverage
The kind of party that a register lists.
Type: one of intermediaries, insurers.
RegisterSource
A public register that the registry reads.
| Field | Type | Required | Description |
|---|---|---|---|
country |
CountryCode |
Yes | |
subdivisions |
list of SubdivisionCode |
Subdivisions that this source covers, for example one US state. Omit when it covers the whole country. | |
register |
string | Yes | Name of the register, for example "ORIAS" or "FCA Register". |
regulator |
string | Yes | Authority that keeps the register, or that supervises its entries. |
covers |
list of RegisterCoverage |
Yes | |
identifier_type |
RegisterIdentifierType |
Yes | |
access |
SourceAccess |
Yes | |
url |
Url |
Yes | Public home page of the register. |
R2. Common types
DomainName
Host name, lower case, with no scheme, port or path, for example "pets.example.com".
Type: string. Pattern: ^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)+$.
RegisterIdentifier
An entry in a public register, as an agent or a listing gives it.
| Field | Type | Required | Description |
|---|---|---|---|
country |
CountryCode |
Yes | Country of the register. |
identifier_type |
RegisterIdentifierType |
Yes | |
identifier |
string | Yes | |
register |
string | Name of the register. Give it when identifier_type is "other". |
R3. Listing
ListedDistributor
A server that the registry lists.
| Field | Type | Required | Description |
|---|---|---|---|
legal_name |
string | Yes | |
trading_name |
string | ||
lei |
Lei |
||
domain |
DomainName |
Yes | |
mcp_url |
Url |
Yes | MCP endpoint of the server: the url of the apis entry of type "mcp" in poppy.json. |
poppy_url |
Url |
Yes | URL of the PAP poppy.json of the domain. |
roles |
list of DistributorRole |
Yes | |
conformance_level |
ConformanceLevel |
Yes | |
lines |
list of ProductLine |
Yes | Lines the server can quote, as it declares them. |
countries |
list of CountryCode |
Yes | Countries where the server sells, as it declares them. |
subdivisions |
list of SubdivisionCode |
Subdivisions of the country asked where the server holds a licence. Omit when its licence covers the whole country. | |
insured_families |
list of InsuredFamily |
Families of the insured in the underwriting scopes of its products. | |
licence_check |
ListingCheck |
Yes | |
listed_since |
DateString |
Yes | Date when the registry first listed the server. |
ListingCheck
The last licence check of a listed server, for the country asked.
| Field | Type | Required | Description |
|---|---|---|---|
entries |
list of RegisterIdentifier |
Yes | The register entries that make the server licensed in the country asked. |
checked_at |
DateTimeString |
Yes | When the registry last read these entries in their registers. |
R4. Search
SearchDistributorsParams
Params of search_distributors. The params describe a market, never a person.
| Field | Type | Required | Description |
|---|---|---|---|
country |
CountryCode |
Yes | Country where the customer buys. |
subdivision |
SubdivisionCode |
Subdivision where the customer buys, for example a US state. | |
line |
ProductLine |
||
insured_family |
InsuredFamily |
Family of the insured, as in the underwriting scope of a product, for example "pet" or "dwelling". | |
min_conformance_level |
ConformanceLevel |
Return only servers of this level or above. | |
cursor |
string |
SearchDistributorsResult
Result of search_distributors.
- Each server in
distributorsMUST match every param of the search: the country is in itscountries, the line is in itslines, the subdivision is in itssubdivisionswhen it has some, the insured family is in itsinsured_families, and its level is not belowmin_conformance_level. - The registry MUST return every listed server that matches, across the pages.
- For a country where it lists no server, the registry MUST return the error "country_not_covered", so that an agent does not read an empty list as "no seller exists".
- The order carries no meaning. The registry MUST NOT rank a server for a payment or for any commercial link. It SHOULD shuffle the order for each new search, and keep that order across the pages of the same search.
- An agent MUST NOT show the order to the customer as a ranking.
- A search result is not a licence check. An agent checks the seller with
verify_licencebefore it sends any of the customer's answers.
| Field | Type | Required | Description |
|---|---|---|---|
distributors |
list of ListedDistributor |
Yes | |
next_cursor |
string |
R5. Licence check
SellerSubject
A seller to check. The domain is where the customer's answers go.
| Field | Type | Required | Description |
|---|---|---|---|
domain |
DomainName |
Yes | Domain of the MCP server or the website that receives the customer's answers. |
identifier |
RegisterIdentifier |
Register entry that the seller shows, for example in the legal notice of its website. | |
legal_name |
string | Legal name that the seller shows. |
ProviderSubject
A provider to check, for example from Offer.provider. Give its domain, a register entry, or both.
Variant 1
| Field | Type | Required | Description |
|---|---|---|---|
domain |
DomainName |
Yes | Domain of the provider, for example ProviderRef.domain. |
identifier |
RegisterIdentifier |
Register entry of the provider, for example one of ProviderRef.licences. |
|
legal_name |
string | Legal name of the provider, for example ProviderRef.legal_name. |
Variant 2
| Field | Type | Required | Description |
|---|---|---|---|
identifier |
RegisterIdentifier |
Yes | Register entry of the provider, for example one of ProviderRef.licences. |
legal_name |
string | Legal name of the provider, for example ProviderRef.legal_name. |
DistributorCheckParams
Params of verify_licence for a seller. Every distribution role counts, including an insurer that sells its own products.
The check MUST work for a seller that the registry does not list. An agent can find a seller anywhere on the web, and the check matters most then.
| Field | Type | Required | Description |
|---|---|---|---|
capacity |
distributor |
Yes | |
subject |
SellerSubject |
Yes | |
country |
CountryCode |
Yes | Country where the customer buys. |
subdivision |
SubdivisionCode |
Subdivision where the customer buys. REQUIRED for a country in PER_SUBDIVISION_COUNTRIES, such as the United States. |
|
line |
ProductLine |
ProviderCheckParams
Params of verify_licence for the party that carries the risk, for example the insurer in Offer.provider. Only a provider role counts.
| Field | Type | Required | Description |
|---|---|---|---|
capacity |
provider |
Yes | |
subject |
ProviderSubject |
Yes | |
country |
CountryCode |
Yes | Country where the customer buys. |
subdivision |
SubdivisionCode |
Subdivision where the customer buys. REQUIRED for a country in PER_SUBDIVISION_COUNTRIES, such as the United States. |
|
line |
ProductLine |
VerifyLicenceParams
Params of verify_licence. The params name a company and a market, never a person. A seller check always names the domain that receives the customer's answers, because a register number alone does not prove who runs a website.
Type: DistributorCheckParams or ProviderCheckParams.
LicenceStatus
Status of one register entry, as the registry reads it.
Type: one of active, pending, lapsed, suspended, revoked, not_found, name_mismatch.
LicenceCheck
The result of reading one entry in one public register.
| Field | Type | Required | Description |
|---|---|---|---|
country |
CountryCode |
Yes | |
regulator |
string | Yes | Supervising authority, for example "ACPR", "FCA", or a US state insurance department. |
register |
string | Yes | Name of the public register, for example "ORIAS", "FCA Register", "NIPR". |
identifier_type |
RegisterIdentifierType |
Yes | |
identifier |
string | Yes | |
role |
DistributorRole |
Role that the entry gives. Omit when the status is "not_found". | |
status |
LicenceStatus |
Yes | |
register_status |
string | The status in the words of the register, for example "Authorised" or "Inscrit". | |
categories |
list of string | Register categories, for example ORIAS "COA" or US lines of authority. | |
lines |
list of ProductLine |
Lines that the categories cover, mapped by the registry. Omit when the categories cover every line. | |
subdivisions |
list of SubdivisionCode |
Subdivisions where the entry applies. Omit when it covers the whole country. | |
passports |
list of CountryCode |
Other countries where the entry may operate, under the freedom to provide services or the freedom of establishment (EU and EEA), as the register shows them. | |
name_in_register |
string | Name of the holder in the register. | |
valid_until |
DateString |
Last day of the entry, when the register gives one. | |
access |
SourceAccess |
Yes | How the registry read the register. |
source_date |
DateString |
Date of the data in the source, when it is older than the read, for example the date of a bulk file. | |
checked_at |
DateTimeString |
Yes | When the registry read this entry. |
source_url |
Url |
Yes | Public page where anyone can check the entry, or the search page of the register. |
DomainLink
How the registry tied a domain to register entries. Only "register" and "confirmed" support the verdict "licensed".
Type: one of register, confirmed, claimed, not_linked.
CheckedSubject
What the registry found about the party it checked.
| Field | Type | Required | Description |
|---|---|---|---|
legal_name |
string | Legal name, from the AIP server of the domain or from the register. | |
lei |
Lei |
Legal entity identifier, from the AIP server of the domain or from the register. | |
domain |
DomainName |
||
domain_link |
DomainLink |
How the registry tied the domain to the entries. Present when the params give a domain. | |
listed |
boolean | Yes | True when the registry lists an AIP server on the domain. |
mcp_url |
Url |
MCP endpoint of the listed server. |
NotLicensedReason
Why a party holds no licence for what the agent asked.
Type: one of no_entry, licence_not_active, name_mismatch, role_not_covered, subdivision_not_covered, line_not_covered.
UnknownReason
Why the registry cannot decide.
Type: one of country_not_covered, subdivision_required, register_unavailable, subject_not_identified, domain_not_linked.
LicenceVerdict
The answer to the question of the agent.
verdict: licensed
| Field | Type | Required | Description |
|---|---|---|---|
verdict |
licensed |
Yes | |
message |
string | Yes | Plain-language explanation that the agent can pass to the customer. |
verdict: not_licensed
| Field | Type | Required | Description |
|---|---|---|---|
verdict |
not_licensed |
Yes | |
reason |
NotLicensedReason |
Yes | |
message |
string | Yes | Plain-language explanation that the agent can pass to the customer. |
verdict: unknown
| Field | Type | Required | Description |
|---|---|---|---|
verdict |
unknown |
Yes | |
reason |
UnknownReason |
Yes | |
message |
string | Yes | Plain-language explanation that the agent can pass to the customer. |
VerifyLicenceResult
Result of verify_licence.
The registry tests each entry in this order. An entry covers the question when it passes all five tests: 1. Country: the entry exists, and its country is the country asked or its passports include it. 2. Subdivision: it has no subdivisions, or they include the subdivision asked. 3. Line: it has no lines, or no line is asked, or its lines include the line. 4. Role: for the capacity "provider", its role is a provider role. 5. Status: its status is "active".
The verdict:
- "licensed" when at least one entry covers the question and, if the params give a domain,
domain_linkis "register" or "confirmed". - "unknown" when no entry covers the question and the registry could not read every register that applies, or could not identify the party. Also when an entry covers the question but the domain link is "claimed" or "not_linked".
- "not_licensed" in every other case: the registry read every register that applies, and no entry covers the question. The reason comes from the entry that passed the most tests, and names the first test it failed: country "no_entry", subdivision "subdivision_not_covered", line "line_not_covered", role "role_not_covered", status "name_mismatch" or "licence_not_active".
Rules for the registry:
licencesMUST list every entry that the registry read for the party in the registers that apply, including the entries that are not active.- A verdict MUST rest only on reads made at most
MAX_READ_AGE_DAYSdays beforechecked_at. The registry SHOULD read the register again for each call when the register has an API or a web page. - The registry SHOULD keep each result under its
check_idfor at least five years, so that it can confirm later what it said.
Rules for the agent:
- An agent MUST check the seller, in the capacity "distributor", before it sends any of the customer's answers to that seller. The domain MUST be the domain of the server or the website that receives the answers. The agent gives the customer's country, the subdivision where licences apply per subdivision, and SHOULD give the line.
- An agent MUST check the provider of an offer, in the capacity "provider", before it applies or concludes, when the provider is not the seller.
- On "not_licensed", the agent MUST NOT send the customer's answers to that party, and MUST NOT apply or conclude through it. It MUST tell the customer why.
- On "unknown", the agent MUST tell the customer that the licence could not be checked, and why. It MUST NOT apply or conclude, and SHOULD NOT send the customer's answers. It MAY ask the seller for its register identifier and check again.
- An agent MUST keep each result that it relies on with the record of the sale, and SHOULD give the customer a copy.
| Field | Type | Required | Description |
|---|---|---|---|
check_id |
string | Yes | Identifier of this check, set by the registry. |
params |
VerifyLicenceParams |
Yes | The params of the call, so that the result is a complete record alone. |
subject |
CheckedSubject |
Yes | |
licences |
list of LicenceCheck |
Yes | Every entry the registry read for the party. |
outcome |
LicenceVerdict |
Yes | |
checked_at |
DateTimeString |
Yes | When the registry gave the verdict. |
R6. Country rules
GetCountryRulesParams
Params of get_country_rules.
| Field | Type | Required | Description |
|---|---|---|---|
country |
CountryCode |
Yes | |
subdivision |
SubdivisionCode |
Adds the file of this subdivision, when one exists. | |
line |
ProductLine |
Adds the file of this line in the country, when one exists. |
RulesStatus
Review state of a rules file.
Type: one of draft, endorsed.
RulesFile
One rules file of the buyer skill. The file is Markdown with a YAML front matter. The front matter holds country, version, owner, status, and endorsed_by and reviewed_at when they apply, with the same values as the fields of this object. It also holds subdivision and line for a file of a subdivision or of a line.
| Field | Type | Required | Description |
|---|---|---|---|
country |
CountryCode |
Yes | |
subdivision |
SubdivisionCode |
Present for the file of a subdivision. | |
line |
ProductLine |
Present for the file of a line. | |
version |
string | Yes | Version of the file. A change in the text MUST change it. |
owner |
string | Yes | Who maintains the file: the AIP maintainers, until a regulator takes it over. |
status |
RulesStatus |
Yes | |
endorsed_by |
string | Regulator that endorsed this version. REQUIRED when status is "endorsed". |
|
reviewed_at |
DateString |
Date of the last legal review. Omit when no review happened. | |
language |
LanguageTag |
Yes | |
content |
string | Yes | The whole file, unchanged, front matter included. |
sha256 |
Sha256 |
Yes | SHA-256 of content as UTF-8 bytes. |
url |
Url |
Yes | Public HTTPS address of the same file. |
skill_uri |
string | URI of the same file in the skill that the registry serves over MCP, when it does. |
GetCountryRulesResult
Result of get_country_rules.
filesMUST start with the file of the country. The file of the subdivision and then the file of the line follow, when they exist.- For a country with no rules file, the registry MUST return the error "country_not_covered".
- Each file MUST be the same text as the file of the same version in the skill, so that
sha256is the same in both places. - An agent MUST follow every file of the result. When the registry does not answer, the agent uses the copy in its installed skill, and SHOULD tell the customer which version it used.
| Field | Type | Required | Description |
|---|---|---|---|
files |
list of RulesFile |
Yes |
R7. Errors
RegistryErrorCode
Type: one of country_not_covered, invalid_params.
RegistryError
Error returned in an MCP tool result with isError: true, in structuredContent.error.
A registry tool MUST refuse a call with a param that this file does not define, and MUST NOT keep its value. That is how the registry stays free of customer data.
| Field | Type | Required | Description |
|---|---|---|---|
code |
RegistryErrorCode |
Yes | |
message |
string | Yes |
R8. Tool index
RegistryToolName
Type: one of search_distributors, verify_licence, get_country_rules.
RegistryToolSignatures
Params and result type of each registry tool.
| Field | Type | Required | Description |
|---|---|---|---|
search_distributors |
object with params, result |
Yes | |
verify_licence |
object with params, result |
Yes | |
get_country_rules |
object with params, result |
Yes |