Skip to main content

IO Contracts

IO contracts describe what each tool consumes and produces. They make graph edges, candidate expansion, plan synthesis, and execution diagnostics explainable.

Without contracts, a tool graph can still search by text. With contracts, it can also answer operational questions: "Which tool can produce orderNo?", "Which target requires memberNo?", "Is this missing field user input, context, or auth?"

Contract Model

Each operation can have three contract surfaces:

SurfaceMeaning
consumesFields the operation needs in request path, query, header, cookie, or body
producesFields the operation returns in response body or envelope
linksExplicit or inferred relationships between operations

Contract entries are stored under metadata.api_contract on each ToolSchema.

Contract Fields

Consumes and produces entries may include:

FieldPurpose
nameLeaf field or parameter name
pathLocation inside the request or response schema
locationquery, path, header, cookie, body, or response
requiredWhether the field is required by the operation
kinddata, context, or auth
field_typeJSON schema type when available
enumAllowed values when available
semantic_tagGeneric role such as paging, search, identifier, or producer

Public Contract Index

Use extract_openapi_contract_index() when an adapter needs operation-level facts without depending on private parser helpers.

from graph_tool_call.graphify import extract_openapi_contract_index

index = extract_openapi_contract_index(
"openapi.json",
required_only=False,
skip_deprecated=True,
)

print(index["summary"]["response_schema_coverage"])

for operation in index["operations"]:
print(operation["method"], operation["path"])
print(operation["api_contract"]["consumes"])
print(operation["api_contract"]["produces"])

Index Shape

FieldMeaning
versionContract index schema version
operation_countNumber of operations included
operationsOperation-level contract rows
by_operation_idLookup map from operation id to operation key
by_tool_nameLookup map from tool name to operation key
by_method_pathLookup map from METHOD /path to operation key
summaryCoverage and field-count summary

Each operation row includes method, path, operation id, parameters, request body schema, response schema, content types, security hints, api_contract, openapi, and full normalized metadata.

Field Kind Classification

The engine keeps classification generic:

KindUse
dataBusiness data supplied by the user, a producer tool, or static defaults
contextRuntime context supplied by the adapter, such as tenant or site
authAuthentication or authorization material

Pass adapter-specific field names as options:

artifact = build_openapi_collection_artifact(
"openapi.json",
context_field_names={"mallNo", "siteNo"},
auth_field_names={"Authorization", "accessToken"},
paging_field_names={"page", "size"},
search_filter_field_names={"keyword", "searchType"},
)

The engine should classify the fields. The adapter should provide runtime values.

Contracts improve search and selection through:

  • contract_match score signals
  • producer expansion for required target fields
  • result_shape hints from response structure
  • user input slot detection
  • auth readiness diagnostics
  • failure reason classification

Readiness Checks

Useful thresholds vary by domain, but these are strong warning signs:

  • response_schema_coverage is low for read/search APIs
  • produces_field_count is near zero
  • many required consumes fields have no default, producer, or user slot
  • auth fields are classified as data
  • envelope responses hide the actual business result body

Troubleshooting

SymptomLikely CauseWhat To Inspect
Missing producer toolsResponse schema leaves were not extractedapi_contract.produces
Too many producer toolsCommon field names are too broadproducer cap and semantic tags
Required fields become user promptsContext defaults or producer edges are missingcontext_field_names, graph edges
Auth fields appear in UI formsAuth names were not classifiedauth_field_names, OpenAPI security
List/detail confusionResponse shape is missing or ambiguousresponse_schema, result_shape