ARMS Agent
An LLM agent that standardizes legacy biomedical metadata records into the CEDAR template format.
It fetches the live CEDAR template and queries BioPortal for canonical terms through Model Context Protocol tools, so the constraints it applies are the ones the template holds right now.
This is the agent described in Automated Standardization of Legacy Biomedical Metadata Using an Ontology-Constrained LLM Agent (arXiv:2604.08552). The evaluation harness, the 839-record dataset, and the code for every figure in the paper live in the project repository.
Install
pip install arms-agent
Configure
Three keys are required. Put them in the environment, or in a .env file in the directory you run from:
OPENAI_API_KEY=... # LLM calls
CEDAR_API_KEY=... # fetching CEDAR templates
BIOPORTAL_API_KEY=... # ontology term lookups
Optional: set OPENAI_BASE_URL to route LLM calls through an OpenAI-compatible gateway.
To trace each LLM call, tool call, and agent step to Langfuse, install the extra and set both keys:
pip install 'arms-agent[tracing]'
LANGFUSE_PUBLIC_KEY=...
LANGFUSE_SECRET_KEY=...
LANGFUSE_HOST=... # optional, defaults to Langfuse Cloud
Tracing stays off until both keys are set, and LANGFUSE_TRACING_ENABLED=false switches it off while leaving
the keys in place.
Command line
arms-migrate \
--input legacy-record.json \
--target-schema https://repo.metadatacenter.org/templates/dd5e8653-81cf-470b-b71b-15cab421bb84 \
--output migrated.json \
--model gpt-5-mini
--output takes a file or a directory. Given a directory, the filename comes from the input; left out, the
result lands in your temp directory. --model defaults to gpt-5.6-terra. Add --debug for step-by-step
logging on stderr.
Python
import asyncio, json
from langchain_core.messages import HumanMessage
from arms_agent.agent import build_migration_agent, build_response_format
from arms_agent.prompts import SYSTEM_PROMPT
from arms_agent.tools import all_tools
from arms_agent.workflow import build_workflow
template_iri = "https://repo.metadatacenter.org/templates/dd5e8653-81cf-470b-b71b-15cab421bb84"
legacy = json.load(open("legacy-record.json"))
agent = build_migration_agent(
model="gpt-5-mini",
system_prompt=SYSTEM_PROMPT,
response_format=build_response_format(template_iri),
tools=all_tools,
reasoning_effort="high",
)
result = asyncio.run(
build_workflow(agent).ainvoke(
{
"messages": [
HumanMessage(
content=(
"Migrate the following legacy metadata record to the CEDAR template.\n\n"
f"CEDAR Template IRI: {template_iri}\n\n"
f"Legacy metadata:\n```json\n{json.dumps(legacy, indent=2)}\n```"
)
)
],
"cedar_template_iri": template_iri,
},
config={"recursion_limit": 30},
)
)
print(json.dumps(result["metadata"], indent=2))
The agent answers against a JSON schema built from the template, so the result conforms to the template's field structure. When a model answers without a validated object, a fixed extraction step parses the text into one.
Caching
CEDAR template and BioPortal term responses are cached in SQLite for 24 hours, to keep repeated runs fast and off the rate limits. Override with ARMS_CACHE_DIR and ARMS_CACHE_TTL_SECONDS.
Other settings
| Variable | Default | What it does |
|---|---|---|
OPENAI_EXTRACTION_MODEL |
gpt-4.1-mini |
The model that parses a reply into an object when the main model answers without one. |
OPENAI_COST_MULTIPLIER |
1.0 |
Scales the reported cost when your endpoint charges a fraction of OpenAI's list prices. |
OPENAI_COST_CACHE_DISCOUNT |
true |
Whether the endpoint discounts cached input tokens. |
Costs are local estimates from provider-reported token counts, not billed amounts.
License
BSD 2-Clause.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file arms_agent-1.0.0.tar.gz.
File metadata
- Download URL: arms_agent-1.0.0.tar.gz
- Upload date:
- Size: 52.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0e61d21abc9120314a7f2a5e41cf057b79b2c6b61f429e2ad1b2e0cd025c3c3a
|
|
| MD5 |
3b413ea18b4ac94ea37ddbeef1309c8b
|
|
| BLAKE2b-256 |
a731db8f5f03e9844ac7c0d172b6dcdcb40aa9a102aa6478bc869c9e413bdf40
|
Provenance
The following attestation bundles were made for arms_agent-1.0.0.tar.gz:
Publisher:
release.yml on musen-lab/metadata-standardization-agent
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
arms_agent-1.0.0.tar.gz -
Subject digest:
0e61d21abc9120314a7f2a5e41cf057b79b2c6b61f429e2ad1b2e0cd025c3c3a - Sigstore transparency entry: 2692556277
- Sigstore integration time:
-
Permalink:
musen-lab/metadata-standardization-agent@52b81c2501ebcf4b4594ded55b56172490d842be -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/musen-lab
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@52b81c2501ebcf4b4594ded55b56172490d842be -
Trigger Event:
push
-
Statement type:
File details
Details for the file arms_agent-1.0.0-py3-none-any.whl.
File metadata
- Download URL: arms_agent-1.0.0-py3-none-any.whl
- Upload date:
- Size: 39.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
23442a322b98f055bf27844f51eba17f7f3067ebf9ed0989ef774634740a6e86
|
|
| MD5 |
56f7aca5db5d0402912c2bf844f32902
|
|
| BLAKE2b-256 |
c5cf1a93809b3ec5441fe14443ca9fa75911e44fabe47f4971aec79b1791f4a1
|
Provenance
The following attestation bundles were made for arms_agent-1.0.0-py3-none-any.whl:
Publisher:
release.yml on musen-lab/metadata-standardization-agent
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
arms_agent-1.0.0-py3-none-any.whl -
Subject digest:
23442a322b98f055bf27844f51eba17f7f3067ebf9ed0989ef774634740a6e86 - Sigstore transparency entry: 2692556325
- Sigstore integration time:
-
Permalink:
musen-lab/metadata-standardization-agent@52b81c2501ebcf4b4594ded55b56172490d842be -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/musen-lab
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@52b81c2501ebcf4b4594ded55b56172490d842be -
Trigger Event:
push
-
Statement type: