Checking access…

Skip to main content
Version: v2

Prompt Engineering

This page covers where the Assistant's prompts live, their structure, and how mode selection changes which prompt text is actually sent.

Location moved

All prompts now live in wallet-ai-service's src/app/ccg_ai_assistant/prompts.py β€” not in this repo. src/components/ChatBot/aiConfig.js's unused systemPrompt constant has been deleted.


The prompts, at a glance​

ConstantUsed for
DEFAULT_SYSTEM_PROMPTMain answer-generation system prompt
INTEGRATION_MODE_ADDENDUM / BUSINESS_MODE_ADDENDUMAppended to the base prompt depending on mode
CONDENSE_QUESTION_SYSTEMRewrites a follow-up question into a standalone search query
BODY_GENERATION_SYSTEMSchema-grounded JSON body synthesis for example requests
OPERATION_DISAMBIGUATION_SYSTEMPicks the right API operation from a closed candidate list

Every one of these is a plain Python string constant β€” no external file, no build step, no caching mechanism to warm. A change takes effect on the next wallet-ai-service deploy.


DEFAULT_SYSTEM_PROMPT​

1. Source of Truth
- Use ONLY the content provided in the "Context" section below to answer.
- Do NOT infer, assume, or fill gaps beyond what is explicitly stated.
- If the context does not contain the answer, respond with EXACTLY:
"I could not find that information in the CCG Microsite documentation."

2. Security
- Never generate or suggest handling of raw card data.
- Never hardcode secrets; use placeholders.

3. Citations
- Embed Reference Links inline as markdown links. Never invent URLs β€” for a sub-topic
that isn't its own Reference Links entry, link the enclosing page instead of leaving
it unlinked.

3b. Generated Example Request
- If present, reproduce it VERBATIM inside a fenced ```bash block.
Do not invent an alternative, do not alter field values.

4. Formatting
- No Markdown headings. Bold labels for sections. Backtick underscored identifiers.

Rule 1 is what makes the mandated refusal string reliable β€” it's an exact-match instruction, not a suggestion, and the chain never even calls the LLM at all when retrieval finds nothing (see Overview β€” request flow), so there's no path where the model could hallucinate past an empty context.

Rule 3b is what makes example request generation trustworthy β€” the block was built deterministically or schema-validated before the model ever sees it; the model's only job is to not touch it.


Mode addenda​

Appended to DEFAULT_SYSTEM_PROMPT based on the request's mode field β€” see Mode: Integration vs. Business for the behavioral contract. The prompt text itself:

INTEGRATION_MODE_ADDENDUM:

5. Mode: Integration
Prioritize technical precision over prose:
- Lead with the concrete technical answer before business framing.
- Always include the Generated Example Request block when present,
even if the question doesn't mention "curl" or "example".
- Prefer field names, enum values, and identifiers over paraphrase.

BUSINESS_MODE_ADDENDUM:

5. Mode: Business
Prioritize plain-language process/business explanation:
- Do NOT include curl commands or field-level API details, even if a
Generated Example Request block is present or the question mentions
technical terms.
- Explain the business process, rules, and outcomes in prose.

When mode is omitted, neither addendum is appended β€” response style falls back to a keyword heuristic on the question text (does it mention "curl", "example", "endpoint", etc.).

Modifying a mode addendum​

Edit the constant in prompts.py, redeploy wallet-ai-service. No index changes, no UI changes. Test by sending the same question with each mode value and confirming the response style actually differs β€” a prompt change that doesn't visibly change behavior across a few test queries usually means the addendum text is too weak relative to the base prompt's other rules.


CONDENSE_QUESTION_SYSTEM​

Used only when a session already has prior turns. Given the conversation history and a follow-up ("what about for wallet mode?"), it rewrites the question into a standalone query ("what payment modes are available for wallet sessions?") before retrieval runs β€” so search isn't operating on a pronoun-laden fragment with no context.

If this call fails for any reason, the chain falls back to the original, un-rewritten question rather than failing the whole turn β€” condensing is a quality improvement, not a hard dependency.


BODY_GENERATION_SYSTEM​

1. Use ONLY field names and enum values that literally appear in the
provided JSON Schema. Never invent a field not present in the schema.
2. Populate the object to satisfy the described use case using the
schema's own fields and enum values.
3. Respect the schema's `required` lists and any `minItems` constraints.
4. Output ONLY the raw JSON object. No prose, no markdown fences.

This is intentionally the only rule set the model sees for this call β€” no conversation history, no system-prompt mode addenda, just the schema and the use case. Keeping it isolated makes the output easy to validate (jsonschema.validate) and easy to reason about when something goes wrong, versus if body generation shared a prompt with a dozen other unrelated rules.


OPERATION_DISAMBIGUATION_SYSTEM​

1. Output ONLY one of the given operation ids, copied exactly as given,
or the literal word NONE.
2. Never output an id that is not in the given list.
3. If none of the candidates are clearly what the question is asking
about, output NONE.
4. No explanation, no punctuation, no extra text.

This call only fires when operation matching is genuinely ambiguous (multiple distinct candidates, no clear title match) β€” most questions never reach it. The output is validated against the actual candidate set before being trusted; a response that isn't exactly one of the given ids (hallucinated, malformed, or just wrong) is treated as NONE, never as "close enough."


Adding a new prompt​

Follow the existing pattern: a plain string constant in prompts.py, imported where it's used in chain.py. Keep each prompt scoped to one concern (don't fold a new capability's rules into DEFAULT_SYSTEM_PROMPT if it only applies to specific requests β€” see how BODY_GENERATION_SYSTEM and OPERATION_DISAMBIGUATION_SYSTEM are kept separate for exactly this reason).