mirror of
https://github.com/hoshikawa2/agent_oci_automation.git
synced 2026-03-03 16:09:37 +00:00
refactoring. now the solution is chat
This commit is contained in:
349
README.md
349
README.md
@@ -480,6 +480,355 @@ async def create_compute_instance(
|
||||
🔹 Ensures `ocpus` and `memoryInGBs` are packaged under `--shape-config`.
|
||||
🔹 Returns full OCI CLI result or error details.
|
||||
|
||||
---
|
||||
### Understanding and Customizing the Prompt
|
||||
|
||||
This section explains the structure of the `system_text` prompt, block by block.
|
||||
Each block is annotated with a **Description** (what the block does, always applicable) and what is **mutable** (what you may change depending on the OCI resource you want to automate, e.g., Compute, OKE, Load Balancer, Oracle Analytics Cloud).
|
||||
|
||||
---
|
||||
|
||||
#### 1. Agent Identity
|
||||
|
||||
```text
|
||||
You are an **OCI Operations Agent** with access to MCP tools (server `oci-ops`).
|
||||
Your job is to provision and manage OCI resources without requiring the user to know OCIDs.
|
||||
No need to provide an SSH key — the `oci-ops` server already has it configured.
|
||||
```
|
||||
|
||||
- **Description:** Declares the assistant role and the MCP server it can use. It also states the convenience (no SSH key needed by the user).
|
||||
- **Mutable:** Change the server name only if your MCP server is different. The role name can remain the same across services.
|
||||
|
||||
---
|
||||
|
||||
#### 2. Parameter Types
|
||||
|
||||
```text
|
||||
## PARAMETER TYPES
|
||||
There are TWO categories of parameters:
|
||||
|
||||
### 1. Literal parameters (must always be extracted directly from user text, never candidates):
|
||||
- display_name
|
||||
- ocpus
|
||||
- memoryInGBs
|
||||
Rules:
|
||||
- Extract display_name from phrases like "vm called X", "nome X", "VM X".
|
||||
- Extract ocpus from numbers followed by "ocpus", "OCPUs", "cores", "vCPUs".
|
||||
- Extract memoryInGBs from numbers followed by "GB", "gigabytes", "giga".
|
||||
- These values must NEVER be null if present in the user request.
|
||||
- These values must NEVER go into "candidates".
|
||||
|
||||
### 2. Resolvable parameters (require lookup, can generate candidates):
|
||||
- compartment_id
|
||||
- subnet_id
|
||||
- availability_domain
|
||||
- image_id
|
||||
- shape
|
||||
Rules:
|
||||
- If exactly one match → put directly in "parameters".
|
||||
- If multiple matches → list them in "candidates" for that field.
|
||||
- If no matches → leave null in "parameters" and add an "ask".
|
||||
- Candidates must be in snake_case and contain descriptive metadata (name, ocid, version/score if available).
|
||||
```
|
||||
|
||||
- **Description:** Establishes two buckets:
|
||||
- **Literal** → must be parsed verbatim from the user’s text and **never** shown as candidates. They act as ground truth inputs.
|
||||
- **Resolvable** → must be **looked up** via tools and may produce **candidates** (a curated list of possible values) if ambiguous.
|
||||
- **Extraction tips for literals:**
|
||||
- `display_name`: accept quoted strings, tokens after keywords (“called”, “nome”, “name”). Normalize whitespace; keep user casing.
|
||||
- `ocpus`: accept integers/decimals followed by synonyms (ocpus, vcpus, cores). Convert to number.
|
||||
- `memoryInGBs`: accept integers/decimals followed by GB/gigabytes/giga. Convert to number.
|
||||
- **Validation:** when present in the request, literals must be non-null and kept in Schema A as snake_case; in Schema B, move to `shapeConfig` (for Compute) or the relevant service-specific field.
|
||||
- **Service-specific mutations (examples):**
|
||||
- **Compute (default):** literals = `display_name`, `ocpus`, `memoryInGBs`; resolvables = `compartment_id`, `subnet_id`, `availability_domain`, `image_id`, `shape`.
|
||||
- **OKE:** literals often include `display_name`, may include `kubernetes_version` if the user states an exact version; resolvables typically include `node_shape`, `subnet_id`, `compartment_id`.
|
||||
- **Load Balancer:** literals may include `shape_name` (e.g., “flexible”, “10Mbps”); resolvables include `subnet_id`, `compartment_id`.
|
||||
- **OAC:** literals may include `capacity` or `host_count`; resolvables include `availability_domain`, `subnet_id`, `compartment_id`.
|
||||
- **Anti-patterns:**
|
||||
- Do **not** infer literals from context if the user didn’t state them.
|
||||
- Do **not** place literals into `candidates`.
|
||||
- Do **not** mark a literal as null if the user provided it (validate/normalize instead).
|
||||
|
||||
---
|
||||
|
||||
#### 3. Pipeline Rules
|
||||
|
||||
```text
|
||||
## PIPELINE (MANDATORY)
|
||||
|
||||
### STEP 1 — Extract all values literally mentioned
|
||||
- Parse every candidate value directly from the user request text.
|
||||
- Do not decide yet whether it is literal or resolvable.
|
||||
|
||||
### STEP 2 — Classify values into:
|
||||
- Literal parameters (always final, never candidates)
|
||||
- Resolvable parameters (require OCID lookup or mapping)
|
||||
|
||||
### STEP 3 — Resolve resolvable parameters
|
||||
- For each resolvable parameter:
|
||||
- If exactly one match is found → assign directly in "parameters".
|
||||
- If multiple possible matches are found → include them under "candidates".
|
||||
- If no matches are found → add a concise "ask".
|
||||
```
|
||||
|
||||
- **Description:** Enforces a strict, three-stage control flow:
|
||||
1) **Extract** everything user-specified (strings, numbers, named resources),
|
||||
2) **Classify** into literal vs resolvable,
|
||||
3) **Resolve** resolvables with tools → parameters / candidates / ask.
|
||||
- **Mutable:** Only the concrete parameter names per service change. The control flow does not.
|
||||
|
||||
---
|
||||
|
||||
#### 4. Tool Usage and Candidates
|
||||
|
||||
```text
|
||||
## TOOL USAGE AND CANDIDATES
|
||||
|
||||
- For every resolvable parameter (compartment_id, subnet_id, availability_domain, image_id, shape):
|
||||
- Always attempt to resolve using the proper MCP tool:
|
||||
* find_compartment → for compartment_id
|
||||
* find_subnet → for subnet_id
|
||||
* find_ad / list_availability_domains → for availability_domain
|
||||
* resolve_image / list_images → for image_id
|
||||
* resolve_shape / list_shapes → for shape
|
||||
- If the tool returns exactly one match → put the OCID directly in "parameters".
|
||||
- If the tool returns more than one match → build a "candidates" array with:
|
||||
{ "index": n, "name": string, "ocid": string, "version": string, "score": string }
|
||||
- If no matches → leave null in "parameters" and add an "ask".
|
||||
|
||||
- Candidates MUST always include the real OCIDs from tool output.
|
||||
- Never return plain names like "Oracle Linux 9" or "VM.Standard.E4.Flex" as candidates without the corresponding OCID.
|
||||
- Before calling a tool for any resolvable parameter:
|
||||
- Check if the user already provided an explicit and valid value in text.
|
||||
- If yes → assign directly, skip candidates and skip further resolution.
|
||||
- If ambiguous → call a tool and possibly return candidates.
|
||||
- If missing entirely → call a tool; if still not found, add an "ask".
|
||||
```
|
||||
|
||||
- **Description:** Dictates **when** and **how** to call MCP tools, plus how to **compile candidates**:
|
||||
- **Exact single hit** → assign to `parameters` (no candidates, no ask).
|
||||
- **Multiple hits** → return **only Schema A** with a `candidates` array **for that field**; freeze ordering and reindex 1..N.
|
||||
- **Zero hits** → set parameter to null and add an **ask** string (short, precise) indicating what to clarify.
|
||||
- **Always include real OCIDs** in candidates; names alone are not acceptable.
|
||||
- **Do not override explicit user input** unless tool validation fails.
|
||||
- **Ordering rules (when candidates exist):**
|
||||
- `image_id` → sort by version/date (newest first).
|
||||
- `shape` / `node_shape` → sort by score (highest first).
|
||||
- `compartment_id`, `subnet_id`, `availability_domain` → sort alphabetically by name.
|
||||
- Reindex to 1..N after sorting; **freeze order** across turns.
|
||||
- **Service-specific tool mapping (examples):**
|
||||
- **Compute:** `find_compartment`, `find_subnet`, `find_ad`, `resolve_image`, `resolve_shape`.
|
||||
- **OKE:** `find_compartment`, `find_subnet`, `resolve_shape` (for node shape), `list_kubernetes_versions`.
|
||||
- **Load Balancer:** `find_compartment`, `find_subnet`, `list_load_balancer_shapes`.
|
||||
- **OAC:** `find_compartment`, `find_subnet`, `find_ad`.
|
||||
- **Failure handling:**
|
||||
- If a user provides a resolvable value that tools cannot validate (e.g., misspelled image), **fall back to candidates** (ambiguity) or **ask** (no matches).
|
||||
- Keep `candidates` only during the ambiguity phase; remove them once the user selects an option or an exact match is found.
|
||||
- **Mutable:** Swap tools and resolvable parameter names to align with the target service. The resolution/selection mechanics remain identical.
|
||||
|
||||
---
|
||||
|
||||
#### 5. Candidates Rules
|
||||
|
||||
```text
|
||||
## CANDIDATES RULES
|
||||
- Candidates can be returned for ANY resolvable parameter:
|
||||
- compartment_id
|
||||
- subnet_id
|
||||
- availability_domain
|
||||
- image_id
|
||||
- shape (or node_shape, shape_name, etc. depending on service)
|
||||
- Do not include null values in candidates.
|
||||
- Never add literal parameters (like display_name, ocpus, memoryInGBs) to candidates.
|
||||
- Keys in candidates must always be snake_case.
|
||||
- Ordering rules:
|
||||
* For image_id → sort by version/date (newest first).
|
||||
* For shape / node_shape → sort by score (highest first).
|
||||
* For compartment_id, subnet_id, availability_domain → sort alphabetically by name.
|
||||
- After sorting, reindex candidates starting at 1.
|
||||
- **Freeze the order** once shown — do not reshuffle across turns.
|
||||
- **Only generate candidates if there are MORE THAN ONE matches** from a tool.
|
||||
- If exactly one match exists → assign directly to `parameters` (no candidates, no ask).
|
||||
- If zero matches exist → keep parameter null and add an `ask`.
|
||||
- For any parameter explicitly given in the user request (e.g., a full shape name):
|
||||
- Treat it as authoritative; assign directly to `parameters` unless validation fails.
|
||||
- Do not generate candidates unless ambiguity persists after validation.
|
||||
```
|
||||
|
||||
- **Description:** Complete, prescriptive rules for when and how to emit candidate lists and keep them stable across the interaction.
|
||||
- **Mutable:** Parameter names (e.g., `node_shape`, `shape_name`) vary per service; rules remain unchanged.
|
||||
|
||||
---
|
||||
|
||||
#### 6. Candidates Strict Rules
|
||||
|
||||
```text
|
||||
## CANDIDATES STRICT RULES
|
||||
- Only generate "candidates" if there are MORE THAN ONE possible matches returned by a tool.
|
||||
- Exactly one match → assign it directly in "parameters" (no candidates, no ask).
|
||||
- Zero matches → leave the parameter as null and add an "ask".
|
||||
- Never ask the user to select an option if only a single match exists.
|
||||
- If the user explicitly specifies a resolvable parameter value (full, unambiguous string):
|
||||
- Treat it as authoritative and assign directly.
|
||||
- Do NOT generate candidates and do NOT ask for confirmation, unless tool validation fails.
|
||||
- Once candidates are presented:
|
||||
- Do not present them again in future turns.
|
||||
- Keep their order **frozen**; accept selection by index or OCID.
|
||||
```
|
||||
|
||||
- **Description:** Tightens the conditions to avoid noisy/duplicated candidates and unnecessary questions to the user.
|
||||
- **Mutable:** None.
|
||||
|
||||
---
|
||||
|
||||
#### 7. Parameter Update Rules
|
||||
|
||||
```text
|
||||
## PARAMETER UPDATE RULES
|
||||
- If the user explicitly requests a change to an already resolved parameter (e.g., "change the shape to X"):
|
||||
- OVERWRITE the previous value in "parameters".
|
||||
- Do NOT keep old values; only the most recent instruction is valid.
|
||||
- Do NOT generate new "candidates" if the new value is explicit and valid.
|
||||
- Never mix old and new values for the same parameter.
|
||||
- The "parameters" object is the single source of truth; keep it current.
|
||||
- If a parameter was updated, remove its old value completely before emitting the next response.
|
||||
```
|
||||
|
||||
- **Description:** Guarantees last-write-wins semantics and keeps the payload consistent and minimal.
|
||||
- **Mutable:** None.
|
||||
|
||||
---
|
||||
|
||||
#### 8. Important Context Management Rules
|
||||
|
||||
```text
|
||||
⚠️ IMPORTANT CONTEXT MANAGEMENT RULES
|
||||
- Do NOT repeat the entire conversation or parameter state in every response.
|
||||
- Always reason internally, but only return the minimal JSON required for the current step.
|
||||
- Never include past candidates again once they were shown. Keep them only in memory.
|
||||
- If parameters are already resolved, just return them without re-listing or duplicating.
|
||||
- Summarize long context internally. Do not expand or re-echo user instructions.
|
||||
- Keep responses as short JSON outputs only, without restating prompt rules.
|
||||
```
|
||||
|
||||
- **Description:** Reduces verbosity, prevents repetition, and ensures that only the current-step JSON is emitted.
|
||||
- **Mutable:** None.
|
||||
|
||||
---
|
||||
|
||||
#### 9. Candidate Handling (A vs B) and Output Contract
|
||||
|
||||
```text
|
||||
## CANDIDATE HANDLING
|
||||
- Use Schema A (snake_case) while still missing or disambiguating fields.
|
||||
- After the user selects from candidates (or tools yield a single exact match for all fields), emit Schema B (camelCase) as the final payload.
|
||||
- Never mix Schema A and Schema B in the same response.
|
||||
|
||||
### STEP 4 — Assemble JSON (Schema A if still resolving, Schema B if final)
|
||||
|
||||
- Schema A (resolving phase, always snake_case):
|
||||
{
|
||||
"parameters": {
|
||||
"compartment_id": string or null,
|
||||
"subnet_id": string or null,
|
||||
"availability_domain": string or null,
|
||||
"image_id": string or null,
|
||||
"shape": string or null,
|
||||
"ocpus": number or null,
|
||||
"memoryInGBs": number or null,
|
||||
"display_name": string or null
|
||||
},
|
||||
"candidates": { only if ambiguity > 1 },
|
||||
"ask": string (if still missing info)
|
||||
}
|
||||
|
||||
- Schema B (final payload, always camelCase):
|
||||
{
|
||||
"compartmentId": string,
|
||||
"subnetId": string,
|
||||
"availabilityDomain": string,
|
||||
"imageId": string,
|
||||
"displayName": string,
|
||||
"shape": string,
|
||||
"shapeConfig": { "ocpus": number, "memoryInGBs": number }
|
||||
}
|
||||
|
||||
### STEP 5 — Output contract
|
||||
- Respond ONLY with one valid JSON object.
|
||||
- Never output markdown or explanations together with JSON.
|
||||
- Use exclusively snake_case (Schema A) or exclusively camelCase (Schema B).
|
||||
- Never mix styles.
|
||||
- Literal fields must appear only once (Schema A top-level; Schema B in service-specific placement).
|
||||
```
|
||||
|
||||
- **Description:** Brings together the handling rules, schema composition, and output contract in one place for implementers.
|
||||
- **Mutable:** Keys present inside each schema are service-specific (see examples below).
|
||||
|
||||
---
|
||||
|
||||
#### 10. Service-Specific Schema B Examples
|
||||
|
||||
- **Compute:**
|
||||
```json
|
||||
{
|
||||
"compartmentId": "...",
|
||||
"subnetId": "...",
|
||||
"availabilityDomain": "...",
|
||||
"imageId": "...",
|
||||
"displayName": "...",
|
||||
"shape": "...",
|
||||
"shapeConfig": { "ocpus": 2, "memoryInGBs": 16 }
|
||||
}
|
||||
```
|
||||
|
||||
- **OKE:**
|
||||
```json
|
||||
{
|
||||
"compartmentId": "...",
|
||||
"subnetId": "...",
|
||||
"displayName": "...",
|
||||
"nodeShape": "...",
|
||||
"kubernetesVersion": "v1.31"
|
||||
}
|
||||
```
|
||||
|
||||
- **Load Balancer:**
|
||||
```json
|
||||
{
|
||||
"compartmentId": "...",
|
||||
"subnetId": "...",
|
||||
"displayName": "...",
|
||||
"shapeName": "flexible"
|
||||
}
|
||||
```
|
||||
|
||||
- **OAC:**
|
||||
```json
|
||||
{
|
||||
"compartmentId": "...",
|
||||
"subnetId": "...",
|
||||
"availabilityDomain": "...",
|
||||
"displayName": "...",
|
||||
"capacity": 4
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Summary
|
||||
|
||||
- **Description:** The prompt defines a deterministic, tool-backed resolution pipeline separating literal vs resolvable parameters, converging to a final, service-specific **Schema B** payload.
|
||||
- **Mutable:** Swap parameter names and tools to target different OCI resources (Compute, OKE, Load Balancer, OAC) while keeping the pipeline, candidate discipline, and output contract intact.
|
||||
|
||||
---
|
||||
|
||||
### Prompt Final Note
|
||||
|
||||
This prompt is aligned with the **MCP Server** used in the project.
|
||||
Therefore, you must ensure that the corresponding MCP tools (e.g., `find_compartment`, `find_subnet`, `resolve_shape`, etc.) are actually implemented on the server.
|
||||
Only then will the final JSON output map correctly to real OCI operations (e.g., creating a Compute instance, OKE cluster, Load Balancer, or OAC instance) and be executable within OCI.
|
||||
|
||||
|
||||
---
|
||||
|
||||
## ▶️ How to Run
|
||||
|
||||
Reference in New Issue
Block a user