Calling rietx from a program¶
Two calls carry the whole integration surface. capabilities() says what this
build can do; agent.refine_json does it.
For agents
This chapter is the machine-facing half of the package, and every shape in it
was chosen for a caller that branches on a field rather than one that reads a
sentence. You can read all of it from a REPL, and capabilities() is the
fastest way to answer “did my jax extra take?”, but that is not what it is
for.
refine_json: one call, five tasks¶
agent.refine_json takes a dict and returns a dict. It never raises and never
returns a traceback:
from rietx import agent
envelope = agent.refine_json({"task": "capabilities-probe-is-not-a-task"})
envelope["ok"], envelope["error"]["code"]
Success is {"ok": true, …} with exactly one of result, series,
indexing or suggestion set, so a consumer branches on the arm that arrived.
|
Does |
Answers in |
|---|---|---|
|
fits one pattern |
|
|
fits N patterns as one joint residual |
|
|
chains N patterns by warm start |
|
|
determines a unit cell from peaks or a pattern |
|
|
ranks held parameters by predicted Δχ², no solve, no mutation |
|
The four arms are separate because they are different shapes. For indexing the
shape is the rule: the serialized answer carries no cell key, because a powder
pattern does not measure one cell. It measures a ranked set of candidates, and a
singleton would be a confident guess.
Failure is {"ok": false, "error": {code, message, suggestion, details}}. That
is the grammar of a Diagnostic, so a consumer keeps one vocabulary for “the
fit warns” and “the call failed”. Three codes, closed: INVALID_REQUEST (with
per-field dot-paths in details), BACKEND_UNAVAILABLE (a valid backend name
whose optional dependency is not installed here), and REFINEMENT_FAILED.
Two companions ride beside whichever arm arrived, rather than being arms themselves:
evidence— the answer projected for a reasoning consumer.trajectory— the report at every stage boundary, off by default; ask withreport_trajectory: truefor a run you will read whole. A converged report is routinely the least informative one in the run. A plan absorbs an error it cannot free into whatever it can, then arrives converged with nothing to suggest, while its own first stage named the cause. Each rung’s actions are the ones the plan you ran will not fix. The default was measured, not assumed: two eval rounds found consumers handed the rungs unasked decided no better at more calls, so both halves of the surface now default off (Refinement.fit(stage_reports=True)is the library spelling, off becausefitis called in loops).
Registering rietx as a tool¶
agent.tool_definition returns a ready-to-register definition — name,
description, input_schema. agent.request_schema and
agent.response_schema are the JSON Schemas alone.
from rietx import agent
definition = agent.tool_definition()
sorted(definition)
agent.request_schema()["$defs"] is not None
The vocabularies inside that schema are quoted from the live registries. The backend, solver, plan and indexing-engine names come from the same tuples the package dispatches on, and a meta-test fails when a registered member is missing from the exported schema. A third engine cannot ship invisible.
For agents
That description is the first thing a calling agent reads about this package,
before any schema, any result and any part of this manual. It therefore carries
the two rules agents get wrong most often: read the diagnostics before the
statistics, and read the whole trajectory rather than only the final report.
It also points at docs/AGENT_PROTOCOL.md by repository-relative path, and a
pip install gets the package without the docs/ tree. Until that is resolved
at release, put the protocol into your agent’s context yourself, from
the copy in the repository.
capabilities()¶
One call answers what this build supports, and every arm is quoted from a live registry rather than typed:
from rietx import capabilities
caps = capabilities()
[plan.name for plan in caps.plans]
[engine.name for engine in caps.indexing_engines]
sorted(caps.features)
Capabilities.backends,Capabilities.solvers,Capabilities.modes,Capabilities.anodes— the dispatch vocabularies. AnAnodeCapabilitycarries its ownAnodeCapability.wavelengthsandAnodeCapability.kbeta.Capabilities.plans— eachPlanCapabilitywithPlanCapability.title,PlanCapability.description,PlanCapability.modesandPlanCapability.when_to_use, so a program can offer the choice in its own UI without hard-coding a list.PLAN_INFOis the same table in the library.Capabilities.reader_formats— every pattern formatread_patternopens. EachReaderCapabilitycarries its ownReaderCapability.sniff(how the file is recognised),ReaderCapability.sigma(where the uncertainties come from, which differs per vendor) andReaderCapability.refuses(what it declines, and why).Capabilities.reader_optionsdocumentsscan=,block=and the rest.Capabilities.indexing_enginesandCapabilities.search_presets, withSearchPresetCapability.typical_secondsandSearchPresetCapability.total_budget_seconds. An indexing search is budgeted, and a caller that has to promise a response time reads it here.Capabilities.features— feature flags, each derived from the thing it reports (a schema field’s presence, a top-level export’s existence) rather than written as a literaltrue. A flag flips by itself when its feature lands.
Quote this call rather than transcribing its contents. The reader-format list went from five to ten in two days once, and a table in prose would have been wrong by the following week.
Versioned contracts¶
Capabilities reports six version strings. They are separate because they move
independently:
Field |
Versions |
|---|---|
|
the pydantic schemas — the model, the pattern, the result |
|
the |
|
the streaming event ladder |
|
the |
|
the |
|
the indexing gates, caveat and grade vocabularies |
Capabilities.package_version is the seventh string, and the only one that
moves on every release. Store the contract versions alongside any result you store: a
threshold compared across two report_thresholds_version values compares two
different questions.
Further reading: the agent protocol¶
This chapter describes the surface.
docs/AGENT_PROTOCOL.md
covers the half an integrator cannot derive from a schema: the turn-on order,
the degeneracies to memorise, what to check before believing a number, how to
read an abstention, and the measured findings that should change what a calling
agent does.