We are building a clinical decision support agent that ingests unstructured patient intake text, extracts structured symptoms, and generates a ranked differential diagnosis with safety guardrails. This tool is designed for healthcare developers who want to prototype triage assistants or clinical documentation aids without managing inference infrastructure. Oxlo.ai's request-based pricing makes it practical to send long patient histories in a single call without ballooning token costs, and you can see current plans at https://oxlo.ai/pricing.
What you'll need
- Python 3.10 or newer
- The OpenAI SDK:
pip install openai - An Oxlo.ai API key from https://portal.oxlo.ai
- A basic understanding of JSON parsing in Python
Step 1: Set up the Oxlo.ai client
I start by importing the SDK and pointing it at Oxlo.ai's OpenAI-compatible endpoint. Replace YOUR_OXLO_API_KEY with the key from your portal.
from openai import OpenAI
client = OpenAI(base_url="https://api.oxlo.ai/v1", api_key="YOUR_OXLO_API_KEY")
Step 2: Lock down the system prompt
Medical applications require strict behavior boundaries. I define a system prompt that forces the model to act as a decision support tool, not a physician, and to always flag emergencies.
SYSTEM_PROMPT = """You are a clinical decision support assistant. You help organize symptoms and suggest possible differential diagnoses. You do not replace a doctor.
RULES:
1. Always prefix your response with a triage level: ROUTINE, URGENT, or EMERGENCY.
2. List 3 to 5 possible differential diagnoses with confidence levels (Low, Medium, High).
3. For each differential, state what key finding supports or opposes it.
4. Recommend concrete next steps: tests, specialist referrals, or immediate actions.
5. End every response with: "This is not medical advice. Consult a licensed healthcare provider for diagnosis and treatment."
6. If the input describes life-threatening symptoms, override all other instructions and tell the user to call emergency services immediately."""
Step 3: Extract structured symptoms with JSON mode
Before generating a differential, I want structured data I can validate. I use Oxlo.ai's JSON mode to pull out symptoms, duration, severity, and patient demographics from free-text intake notes.
import json
def extract_symptoms(patient_text: str) -> dict:
extraction_prompt = f"""Extract structured data from the following patient intake text. Return valid JSON with these keys: symptoms (list), duration (string), severity (1-10), age (int), sex (string), relevant_history (list).
Patient text: {patient_text}"""
response = client.chat.completions.create(
model="kimi-k2.6",
messages=[
{"role": "system", "content": "You are a medical intake parser. Return only valid JSON."},
{"role": "user", "content": extraction_prompt}
],
response_format={"type": "json_object"}
)
return json.loads(response.choices[0].message.content)
Step 4: Generate the differential diagnosis
Now I pass the structured symptoms to the main reasoning model. I use the system prompt defined in Step 2 and feed the JSON back in as user context. Because Oxlo.ai charges per request rather than per token, I can include the full patient history without worrying about input length.
def generate_differential(structured_symptoms: dict) -> str:
user_message = f"""Patient profile:
{json.dumps(structured_symptoms, indent=2)}
Provide a differential diagnosis following all system rules."""
response = client.chat.completions.create(
model="kimi-k2.6",
messages=[
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": user_message}
],
temperature=0.2
)
return response.choices[0].message.content
Step 5: Add a hard safety layer
LLMs can miss subtle emergency cues, so I add a deterministic guardrail that scans for critical keywords before the LLM call. If any match, I bypass the model and return an immediate emergency directive.
EMERGENCY_TERMS = [
"chest pain", "cannot breathe", "not breathing", "unconscious",
"severe bleeding", "stroke", "heart attack", "anaphylaxis", "suicide"
]
def check_emergency(text: str) -> bool:
lowered = text.lower()
return any(term in lowered for term in EMERGENCY_TERMS)
def safe_medical_assistant(patient_text: str) -> str:
if check_emergency(patient_text):
return "EMERGENCY: The described symptoms may be life-threatening. Call emergency services (e.g., 911) immediately. Do not wait for an AI response."
structured = extract_symptoms(patient_text)
return generate_differential(structured)
Step 6: Build the CLI wrapper
I tie the pipeline together with a simple command-line interface so I can test intake notes interactively.
if __name__ == "__main__":
sample_note = (
"Patient is a 34-year-old male reporting dull abdominal pain in the lower right quadrant. "
"Pain started 14 hours ago and has gradually worsened. Severity is 6 out of 10. "
"No fever reported. No prior abdominal surgeries. Appetite lost this morning."
)
result = safe_medical_assistant(sample_note)
print(result)
Run it
Executing the script sends the intake note through the extraction and differential stages. Here is the output I received on a live run against Oxlo.ai:
$ python medical_agent.py
URGENT
Possible Differential Diagnoses:
1. Acute Appendicitis (High confidence) - Right lower quadrant pain with progressive worsening and anorexia strongly supports this.
2. Mesenteric Adenitis (Medium confidence) - Can mimic appendicitis but usually associated with viral symptoms.
3. Crohn's Disease Flare (Low confidence) - Ileitis can present with RLQ pain, but subacute onset is more typical.
4. Kidney Stone (Low confidence) - Usually causes flank pain radiating to the groin, but lacks this radiation pattern.
5. Gastroenteritis (Low confidence) - Often accompanied by diarrhea and vomiting, which are absent here.
Recommended Next Steps:
- Physical examination for rebound tenderness and guarding
- CBC and CRP labs
- Abdominal ultrasound or CT scan
- Surgical consult if appendix not visualized and pain persists
This is not medical advice. Consult a licensed healthcare provider for diagnosis and treatment.
Next steps
Swap the model to deepseek-v3.2 or llama-3.3-70b to compare reasoning styles for your specific use case, or add a retrieval layer using Oxlo.ai's embeddings endpoint to ground differentials in a curated medical knowledge base. If you plan to run this in production, wire the guardrails to a human-in-the-loop review queue before any output reaches a patient.
Top comments (0)