BUILD AN AGENT WITHGROUNDING
Grounding checks whether an answer is supported
by the documents you give it.
Employees receive a one-time home office equipment allowance of $500. Submit receipts within 30 days of purchase.
home-officeYou receive a one-time home office allowance of $500. Submit your receipts within 30 days of purchase.
The policy supports the allowance and receipt deadline.
source_ids: ["home-office"]trueBuild an agent that answers questions from your documents, then checks each answer against the evidence before showing it in chat.
We will connect to a LiteLLM gateway, load a policy, generate and check an answer, then display the grounding result. The Python snippets form one async request handler. Start with one document; connect your retriever once you can inspect the complete flow.
This guide uses the unreleased SDK helper #49469, native endpoint response #49460, and Bedrock assessment setting #49470, for issue #49217. Use that implementation for both your SDK and gateway until release. The template at the end pins the complete revision.
Step 1. Connect to your gateway
Configure your SDK once. Use your gateway URL and a virtual key with access to the agent model and grounding guardrail:import osimport litellm
litellm.api_base = os.environ["LITELLM_API_BASE"]litellm.api_key = os.environ["LITELLM_API_KEY"]
We use a model named agent on the gateway. The openai/ prefix below selects the OpenAI-compatible transport; the gateway can route agent to a model from another provider.
For the grounding check, use Amazon Bedrock Guardrails through LiteLLM. AWS maintains the assessment service, and you can use it with answers from other model providers. Add this to your gateway configuration:guardrails: - guardrail_name: answer-grounding litellm_params: guardrail: bedrock mode: post_call default_on: false guardrailIdentifier: os.environ/BEDROCK_GUARDRAIL_ID guardrailVersion: os.environ/BEDROCK_GUARDRAIL_VERSION aws_region_name: os.environ/AWS_REGION_NAME contextual_grounding_from_messages: true outputScope: FULL
Create an AWS guardrail with contextual grounding enabled. For conversational answers, choose Standard tier and its required cross-Region inference profile. Set the AWS filter action to NONE so your application can receive an unsupported finding and decide what to display. Set outputScope: FULL in LiteLLM to receive supported assessments too. See AWS setup, filter actions, and full assessments.
default_on: false leaves this guardrail available for the explicit SDK call in step 3. You control when the check runs.
Step 2. Retrieve the evidence
Start with a home office policy. Save this text as home-office.md:Employees receive a one-time home office equipment allowance of $500.Submit receipts within 30 days of purchase.
Load the policy and keep it with the question:from pathlib import Path
question = "How much can I spend on my home office?"evidence = Path("home-office.md").read_text()
source_messages = [ {"role": "system", "content": evidence}, {"role": "user", "content": question},]
Your agent and the grounding service must receive the same evidence. With contextual_grounding_from_messages: true, LiteLLM sends the system text to Bedrock as the grounding source and the user question as the query.
For your own documents, replace the file read with your retriever. Pass only documents the current user can access. Keep previous assistant answers out of the reference evidence.
Step 3. Generate and check the answer
Ask your model to answer from that evidence:completion = await litellm.acompletion( model="openai/agent", messages=[ {"role": "system", "content": "Answer using only this policy:\n" + evidence}, {"role": "user", "content": question}, ],)answer = completion.choices[0].message.content
Then call the grounding guardrail with the answer and source messages:native_result = await litellm.guardrails.apply( "answer-grounding", response=answer, messages=source_messages,)
"answer-grounding" selects the configured guardrail. response=answer tells the SDK to check generated output; the SDK infers the direction. You do not need to provide an input type or a response-format flag.
The call returns the guardrail's native structured findings, after LiteLLM's existing reporting sanitization. For Bedrock, the grounding assessment looks like this illustrative excerpt:{ "contextualGroundingPolicy": { "filters": [{ "type": "GROUNDING", "score": 0.98, "threshold": 0.7, "detected": false }] }}
Bedrock compares the answer with the supplied evidence. It does not verify whether the source document itself is correct. Evaluate the check on supported, contradicted, and incomplete answers from your use case before using it to enforce policy.
Step 4. Show the result in chat
Read the GROUNDING assessments. Require an assessment before showing a positive badge, and check the score against its configured threshold:results = native_result if isinstance(native_result, list) else [native_result]checks_by_result = [ [check for assessment in result.get("assessments", []) for check in assessment.get("contextualGroundingPolicy", {}).get("filters", []) if check["type"] == "GROUNDING"] for result in results]
is_grounded = Noneif checks_by_result and all(checks_by_result): is_grounded = all( check["score"] >= check["threshold"] and not check.get("detected", False) for checks in checks_by_result for check in checks )
Check all returned chunks. Do not infer success from Bedrock's overall action: a report-only guardrail can return NONE with a negative grounding finding.
Return the answer and verdict from your chat backend. In your chat component, show the result beside the answer:export function GroundingBadge({grounded}) { if (grounded == null) { return <span>Grounding check unavailable</span>; }
return ( <span data-status={grounded ? "supported" : "unsupported"}> {grounded ? "Supported by your documents" : "Not supported"} </span> );}
Show the source and the check's explanation.
is_grounded: trueExplain the gap or ask the agent to retry.
is_grounded: falseKeep this separate from a completed check.
no valid verdictA timeout, missing assessment, or invalid result should produce Check unavailable, with no green badge. The template below includes typed response validation and those failure states.
Bedrock evaluates the supplied documents together. Label the references Documents checked; its response does not attribute an answer to an individual document. For an unsupported answer, you can show the gap, retrieve more evidence, or withhold the answer. Wait for the check before rendering if your product gates delivery on the result.
Deploy the complete chat template
You have the core flow: evidence, answer, grounding call, and a verdict beside the response. Use the template to get the complete chat UI, a tool-calling document agent, and validated result handling in a separate repository.git clone https://github.com/BerriAI/litellm-grounded-agent-starter.gitcd litellm-grounded-agent-starteruv syncuv run grounded-agent-demo
Open localhost:8502. Choose Home office allowance for a supported answer, or Check an unsupported answer to see a negative verdict. This local demo uses fixed model and judge responses, labelled in the UI, so you can exercise the SDK, gateway, and chat without provider credentials.
For a live deployment, follow the template's Bedrock setup, replace the included documents with your retriever, and connect your models. The launcher supports local development; deploy the gateway and chat app with your platform's normal service configuration. Add sign-in and document authorization before sharing the app with coworkers. Live AWS execution remains unverified in this example; the template tests its adapter with representative responses.
Key takeaways
Give your agent and grounding guardrail the same evidence. Call litellm.guardrails.apply after the answer exists, read the provider's assessment, and keep supported, unsupported, and failed checks distinct in your UI.
Frequently asked questions
Can I use an existing agent and guardrail?
Yes. Keep your framework and evaluation logic. Replace the answer-generation snippet with your agent's final answer, call litellm.guardrails.apply, and read your guardrail's result schema.
Does LiteLLM generate a second answer for the check?
The SDK invokes your configured guardrail. Bedrock evaluates the supplied answer. A custom LLM judge makes an evaluation request; it does not regenerate the agent's answer to obtain the verdict.
Can I use this with LiteLLM OSS?
The SDK changes and template are open source. Use the linked implementation revision for both the SDK and AI Gateway until release. LiteLLM Enterprise adds controls and support for production deployments.
Recommended reading
Call a guardrail directly, configure Bedrock grounding, and write a custom guardrail.
