The SQL subagent

The billing subagent answers questions like "what is my premium?" or "do I have a balance due?" It needs one thing the supervisor cannot infer from the message alone: a customer_id. The state already has a slot for that. If the id is missing, the subagent politely asks for it instead of hallucinating a customer.

agent_graph.py
python
BILLING_PROMPT = '''You are the billing agent. Use the customer record below to answer.
If no customer_id was provided, ask the user to share it.

User question:
{user_input}

Customer record (JSON):
{record}

Answer clearly. Show premium, balance due, and next steps where relevant.
'''

The prompt includes an explicit fallback: if no customer_id was provided. That branch is handled by the code below through the sentinel string passed in place of the record. The model sees a clear signal instead of an empty field.

agent_graph.py
python
async def billing_agent_node(state: ClaimState) -> Dict[str, Any]:
    customer_id = state.get('customer_id')
    record = get_customer(customer_id) if customer_id else None

    provider = get_llm_provider()
    answer = await provider.generate_text(
        BILLING_PROMPT.format(
            user_input=state.get('user_input', ''),
            record=json.dumps(record, default=str) if record else '(no customer_id provided)',
        ),
        max_tokens=400,
        temperature=0.2,
    )
    return {
        'customer_record': record,
        'answer': answer,
        'citations': [],
    }

The SQL lookup is deterministic. The LLM never writes SQL. It only reads the serialized record and answers in natural language. citations is an empty list because SQL answers do not cite a document, they cite the database row (which you could surface in the UI using customer_record).

Flexibility at the cost of safety and determinism. An LLM that writes SQL can drop tables, leak data across customers with a mistyped JOIN, or time out on an expensive query. In a production copilot, you almost always want a small set of parameterized helpers the agent can call, not arbitrary query generation. You lose the "write any query" flexibility and gain predictability, observability, and guardrails.

Quiz: Quiz

Loading practice…