Cross-model review: have one LLM check another's output
Why a second model
Have one model produce an answer, then have a different model review it. A reviewer from another model family catches mistakes the author is blind to, because the same model tends to miss the same errors twice. It is a practical check against hallucinations and gaps.
On FastMetal both calls go to the same endpoint with the same key. Switching from a GPT model to a Claude model is a change to the model field, with no second account or contract.
Step 1: draft with model A
Give the first model the task:
curl https://api.fastmetal.ai/v1/chat/completions \
-H "Authorization: Bearer $FASTMETAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-5.6-sol",
"messages": [{"role": "user", "content": "Fix the bug in this function: ..."}]
}'
Keep the answer; it is the draft for step 2.
Step 2: review with model B
Pass the original task and model A's answer to a model from a different family, with a reviewer's system prompt:
curl https://api.fastmetal.ai/v1/chat/completions \
-H "Authorization: Bearer $FASTMETAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "anthropic-claude-opus-5",
"messages": [
{"role": "system", "content": "You are a strict reviewer. List the errors, omissions and possible improvements in the answer below."},
{"role": "user", "content": "Original task: ...\n\nAnswer to review: (the output from step 1)"}
]
}'
If model B finds problems, send its critique back to model A and ask for a revision.
The same loop in Python
from openai import OpenAI
client = OpenAI(
api_key="<FASTMETAL_API_KEY>",
base_url="https://api.fastmetal.ai/v1",
)
AUTHOR = "gpt-5.6-sol"
REVIEWER = "anthropic-claude-opus-5"
task = "Fix the bug in this function: ..."
def chat(model, messages):
resp = client.chat.completions.create(model=model, messages=messages)
return resp.choices[0].message.content
draft = chat(AUTHOR, [{"role": "user", "content": task}])
review = chat(REVIEWER, [
{"role": "system", "content": "You are a strict reviewer. List the errors, omissions and possible improvements in the answer below."},
{"role": "user", "content": f"Original task: {task}\n\nAnswer to review:\n{draft}"},
])
revised = chat(AUTHOR, [
{"role": "user", "content": task},
{"role": "assistant", "content": draft},
{"role": "user", "content": f"A reviewer wrote:\n{review}\n\nRevise your answer."},
])
print(revised)
Things that go wrong
- Authentication. Every call needs
Authorization: Bearer $FASTMETAL_API_KEY. - Model ids. Use the exact id from the model catalog; a near miss is an error.
- Balance. Usage is prepaid, and requests are refused once the balance runs out. A review loop makes at least two calls per task, so leave room for them.
Where it fits
The pattern works for code, summaries and translation alike. Tune it to the stakes: a cheaper reviewer for routine checks, a stronger one when the decision matters. The docs cover the API, and the model catalog lists every model you can put in either seat, all on one key and one balance.