- The first prepares the user-facing audit prompt and loads tagging rules from disk.
- The second builds the LLM, converts MCP servers into LangChain-style tools, and injects a strict system-level message containing the tagging rules.
- Review the two source files and their responsibilities.
- Examine how the user prompt and system message are separated and why that reduces hallucinations.
- Highlight the exact places where tagging rules are enforced.
- MCP: https://learn.kodekloud.com/user/courses/mcp-for-beginners
- LangChain: https://learn.kodekloud.com/user/courses/langchain
structure_auditor.py— prepares the user prompt, loads tagging rules, then callsrun_agent.mcp_client.py— builds the LLM, converts MCP servers into LangChain-style tools, composes messages (including the system message), and runs the agent.
run_agent() with the prompt and the rules. Keeping the user prompt focused on the audit task reduces complexity and lets the system message supply non-negotiable policy.
- Explicit role: the model is told it is an auditor for Kubernetes labels focused on FinOps governance.
- Concrete checklist: step-by-step actions — list namespaces, fetch specific resource kinds, report exact labels, evaluate against rules, flag violations, and produce a full summary.
- Anti-hallucination guidance: an explicit instruction to “Use only data returned by the tools. Do not invent labels or resources.”
- Separation of concerns: the tagging rules YAML is not embedded in the user prompt. It is loaded separately and injected as a system message (see below) so the user message remains lean and task-focused.
System messages are the right place for hard constraints (for example, “do not invent labels/reports”) because they are higher-precedence instructions to the model. Put non-negotiable rules and strict policy data (the tagging rules YAML) in a system message, and use the user prompt to describe the audit task itself.
- Tools are converted from MCP servers into LangChain-like tools via
convert_mcp_to_langchain_tools(MCP_SERVERS). - The LLM client is configured by
build_llm(...)using environment variables:OPENAI_MODEL_ID,OPENAI_BASE_URL,OPENAI_API_KEY,OPENAI_TEMPERATURE, andOPENAI_MAX_TOKENS. - If tagging rules are supplied, the client prepends a SystemMessage that embeds the YAML and supplies strict enforcement instructions.
- The user prompt is then supplied as a
HumanMessage. Agents run with both messages present, so the system instructions have higher precedence. - The function cleans up tool resources via the returned
cleanup()coroutine regardless of success or failure.
- Separate the user task (HumanMessage) from the policy and enforcement (SystemMessage). This decreases hallucinations and keeps the task prompt concise.
- Embed tagging rules and strict constraints in the system message so they are treated as non-negotiable by the model.
- Use the model only with data returned by tools; the prompt should require the agent to “report exactly as returned” to avoid invented labels or resources.
- Ensure cleanup coroutines returned by tool conversion functions are awaited to release resources.
- LangChain: https://learn.kodekloud.com/user/courses/langchain
- MCP (MCP for Beginners): https://learn.kodekloud.com/user/courses/mcp-for-beginners
- Kubernetes labels and best practices: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/