Apply Guardrails at Runtime
Add Agent Control to the App
First, wire the Agent Control SDK into the app: add the configuration, install the packages, and register the controllable steps.
Set up the environment
Change into the agent controls folder:
cd ~/workshop/healthcare-assistant/4-app-with-controlsCreate an Agent Control Config Map
Run the following command to create a Kubernetes config map, which the application will use to configure Agent Controls:
kubectl create configmap galileo-agent-control-config \
--from-literal=GALILEO_API_URL="https://api.multitenant.galileocloud.io" \
--from-literal=AGENT_CONTROL_URL="https://console.multitenant.galileocloud.io/api/agent-control" \
--from-literal=AGENT_CONTROL_AGENT_NAME="agent-control-example" \
--from-literal=AGENT_CONTROL_API_KEY_HEADER="Galileo-API-Key" \
--from-literal=AGENT_CONTROL_RUNTIME_AUTH_MODE="jwt" \
--from-literal=AGENT_CONTROL_TARGET_TYPE="log_stream"Add the Agent Control packages
Confirm requirements.txt includes the Agent Control SDK and evaluators:
agent-control-sdk[galileo]>=7.10.0
agent-control-evaluators>=7.10.0
agent-control-evaluator-galileo>=7.10.0Note about the SDK
This workshop was built using the older agent-control packages. For new deployments, we recommend
using the following packages instead:
agent-control-sdk[splunk-ao]>=7.10.0
agent-control-evaluators>=7.10.0
agent-control-evaluator-splunk-ao>=7.10.0Refer to the Agent Control document for details about this newer SDK.
Add the imports and decorate the steps
In agent.py, we’ve added the Agent Control imports at the end of the import section:
from agent_control import ControlSteerError, ControlViolationError, controlThe controls stage uses these in three places (already wired up in this folder):
- The LLM call is wrapped with
@control(step_name=LLM_STEP_NAME), whereLLM_STEP_NAME = "Healthcare Assistant", so the model’s responses can be evaluated, blocked, or steered. - Each tool is registered as a controllable step (
get_patient_info,delete_patient_record, and a sharedretrieval_stepfor search tools) via the helpers inhelpers/agent_control_helpers.py. - The agent enables control spans on the Galileo logger
(
galileo_logger.enable_agent_control()) and registers the steps withinit_agent_control(...)so the console knows which steps exist for this agent.
How block and steer are handled in code
When a control fires, the SDK raises an exception that the agent catches:
ControlViolationError→ the step is blocked; the user gets a friendly blocked message.ControlSteerError→ the step is steered; the agent rebuilds the prompt with the steering guidance and retries (up toMAX_STEER_RETRIES) before falling back to a safe message.
What’s the difference between how the app handles a ControlViolationError and a
ControlSteerError?
