Skip to content

Persist local agent chat hotfix in agent-api template#809

Open
rgranadosd wants to merge 3 commits into
wso2:mainfrom
rgranadosd:persist-agent-chat-hotfix
Open

Persist local agent chat hotfix in agent-api template#809
rgranadosd wants to merge 3 commits into
wso2:mainfrom
rgranadosd:persist-agent-chat-hotfix

Conversation

@rgranadosd
Copy link
Copy Markdown

@rgranadosd rgranadosd commented May 6, 2026

Summary

  • persist the startup wrapper in the agent-api component type template
  • keep the local CORS default for the AMP console
  • make the hotfix reproducible from source control

Summary by CodeRabbit

  • Bug Fixes

    • Improved chat API handling: accepts either message or prompt, stores prompt in history, and provides more robust error handling.
    • Updated CORS to allow requests from an alternate localhost port.
  • Documentation

    • Added a note about external repository import testing with an example to validate agent import and deployment.
  • Chores

    • Reworked workflow template parameters to a structured OpenAPI v3 schema for clearer validation and defaults.

Copilot AI review requested due to automatic review settings May 6, 2026 15:50
@CLAassistant
Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 6, 2026

📝 Walkthrough

Walkthrough

Helm templates and docs updated: agent-api CORS origin changed and its container startup replaced with an inline Python hotfix that relaxes Pydantic Question fields and adjusts chat route validation/error handling; a workflow template gains a structured OpenAPI v3 parameters schema; README adds a note about external repository import testing.

Changes

Agent-API Configuration & Startup Patch

Layer / File(s) Summary
Configuration
deployments/helm-charts/wso2-amp-platform-resources-extension/templates/component-types/agent-api.yaml
CORS allowOrigin default changed from http://localhost:3000 to http://localhost:13000.
Startup Wiring
deployments/.../agent-api.yaml
Replaced container command/args with a multi-line startup sequence that writes /tmp/amp_chat_hotfix.py and runs it during container start.
Data Shape Patch
(inline /tmp/amp_chat_hotfix.py)
Patches Pydantic Question model to make prompt, message, session_id, and context optional.
Control Flow / Route Logic
(inline /tmp/amp_chat_hotfix.py)
Updates chat route to accept message or prompt (normalized to user_prompt), require at least one, store prompt in history, and distinguish HTTPException from generic exceptions.

Workflow Template Parameters Schema

Layer / File(s) Summary
Data Shape / Schema
deployments/helm-charts/wso2-amp-evaluation-extension/templates/workflow-templates/workflow-monitor-evaluation.yaml
Replaced flat inline parameters schema with a structured OpenAPI v3 schema defining nested monitor, agent, environment, evaluation, and publishing objects, types, required fields, defaults, and descriptions.
Wiring / Template Update
same file
The workflow template now references the detailed openAPIV3Schema under parameters to validate inputs.

Documentation Note

Layer / File(s) Summary
Documentation
README.md
Inserted a "Note About External Repository Import Testing" section before the Overview that explains validating agent import/deployment from an external repo and gives an example repository link.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰
I nudged a script into the pod's warm den,
made questions softer, prompts welcome again.
Ports hopped to thirteen‑thousand, bright and new,
startup stitches code where fixes grew.
A bunny's patch — quick, neat, and true.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The pull request description is incomplete. It provides a brief summary but lacks most required template sections including Purpose, Goals, Approach, User stories, Release note, Documentation, and others. Expand the description to follow the repository's PR template by adding Purpose (with issue links), Goals, Approach, Release note, Documentation impact, and other required sections.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: persisting a local agent chat hotfix in the agent-api template, which is the primary focus of the changeset.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
⚔️ Resolve merge conflicts
  • Resolve merge conflict in branch persist-agent-chat-hotfix

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Warning

⚠️ This pull request might be slop. It has been flagged by CodeRabbit slop detection and should be reviewed carefully.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
README.md (1)

9-15: ⚡ Quick win

Consider relocating internal testing notes out of the public README.

This section documents a transient testing artifact (a specific commit of an external third-party repo) and is not relevant to end-users or contributors browsing the README. Placing it before "## Overview" makes it the first substantive content readers see. Consider moving it to CONTRIBUTING.md, a developer wiki page, or a comment in the relevant CI/test config instead.

Additionally, the referenced external repo (kooljo/poc-agent-sdk) is a third-party resource that could be deleted or made private at any time with no notice, making this reference stale.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` around lines 9 - 15, Move the transient testing note under the "##
Note About External Repository Import Testing" header out of the public README
(so it no longer appears before "## Overview"); remove the specific third‑party
repo/commit reference from README.md and instead add it to a non-public
developer document such as CONTRIBUTING.md, a developer wiki page, or as a
comment in the CI/test configuration that runs import/deployment checks; update
README.md to contain only stable, user-facing content and, if needed, add a
brief generic sentence linking to the developer guide for testing details.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@deployments/helm-charts/wso2-amp-platform-resources-extension/templates/component-types/agent-api.yaml`:
- Around line 162-177: The startup hotfix script calls p.read_text() on p =
Path('/workspace/main.py') without checking existence, which causes a
FileNotFoundError for agents that don't include that file; update the script
around the p = Path('/workspace/main.py') / p.read_text() usage to first check
p.exists() (or wrap read_text() in a try/except FileNotFoundError) and skip the
patch/early-return (and print a short message) when the file is absent so the
component doesn't crash on startup.
- Line 179: The container command hardcodes the GCP Buildpack interpreter path
"/layers/google.python.runtime/python/bin/python3" which will fail for non-GCP
workflows listed in allowedWorkflows (e.g., amp-docker,
amp-ballerina-buildpack); replace that hardcoded path with a PATH-resolved
fallback so non-GCP containers simply skip/noop: change the command that runs
"/tmp/amp_chat_hotfix.py" to invoke python via a PATH resolution (e.g., prefer
`python3` if available, fall back to `python` or skip) or wrap invocation in a
shell that checks for a python interpreter before executing the script, ensuring
exec /cnb/process/web still runs when no suitable interpreter exists.
- Around line 168-177: The script unconditionally calls p.write_text(text) and
print("startup hotfix applied") even when no replacement occurred; modify the
flow to detect whether any replacement happened (e.g., track a boolean changed
flag or compare original_text vs text) after attempting both if old in text and
if old2 in text replacements, and only call p.write_text(text) and
print("startup hotfix applied") when changed is true; otherwise skip
writing/printing (or emit a distinct message) so p.write_text, print and the
variables old, old2, new, new2, text reflect actual changes.

---

Nitpick comments:
In `@README.md`:
- Around line 9-15: Move the transient testing note under the "## Note About
External Repository Import Testing" header out of the public README (so it no
longer appears before "## Overview"); remove the specific third‑party
repo/commit reference from README.md and instead add it to a non-public
developer document such as CONTRIBUTING.md, a developer wiki page, or as a
comment in the CI/test configuration that runs import/deployment checks; update
README.md to contain only stable, user-facing content and, if needed, add a
brief generic sentence linking to the developer guide for testing details.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 58ae2b03-b785-47ad-bfee-ca5bf2097c29

📥 Commits

Reviewing files that changed from the base of the PR and between 3416e3a and 4bd2d99.

📒 Files selected for processing (3)
  • README.md
  • deployments/helm-charts/wso2-amp-evaluation-extension/templates/workflow-templates/workflow-monitor-evaluation.yaml
  • deployments/helm-charts/wso2-amp-platform-resources-extension/templates/component-types/agent-api.yaml

Comment on lines +162 to +177
from pathlib import Path

p = Path('/workspace/main.py')
text = p.read_text()
old = """# Pydantic model for handling chat input\nclass Question(BaseModel):\n prompt: str\n"""
new = """# Pydantic model for handling chat input\nclass Question(BaseModel):\n prompt: str | None = None\n message: str | None = None\n session_id: str | None = None\n context: dict | None = None\n"""
if old in text:
text = text.replace(old, new, 1)

old2 = """# Route to chat with OpenAI\n@app.post(\"/chat/\")\ndef ask_openai(question: Question):\n try:\n response = client.chat.completions.create(\n model=\"gpt-4o\",\n messages=[{\"role\": \"user\", \"content\": question.prompt}]\n )\n result = response.choices[0].message.content\n\n # Store chat history in database\n db = SessionLocal()\n db.add(QueryHistory(question=question.prompt, response=result))\n db.commit()\n\n return {\"response\": result}\n except Exception as e:\n raise HTTPException(status_code=500, detail=str(e))\n"""
new2 = """# Route to chat with OpenAI\n@app.post(\"/chat/\")\ndef ask_openai(question: Question):\n try:\n user_prompt = question.message or question.prompt\n if not user_prompt:\n raise HTTPException(status_code=422, detail=\"message or prompt is required\")\n\n response = client.chat.completions.create(\n model=\"gpt-4o\",\n messages=[{\"role\": \"user\", \"content\": user_prompt}]\n )\n result = response.choices[0].message.content\n\n # Store chat history in database\n db = SessionLocal()\n db.add(QueryHistory(question=user_prompt, response=result))\n db.commit()\n\n return {\"response\": result}\n except HTTPException:\n raise\n except Exception as e:\n raise HTTPException(status_code=500, detail=str(e))\n"""
if old2 in text:
text = text.replace(old2, new2, 1)

p.write_text(text)
print("startup hotfix applied")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Critical: unguarded read_text() crashes startup for any agent-api without /workspace/main.py.

p.read_text() raises FileNotFoundError if the target file doesn't exist. Since this ClusterComponentType is shared across all agent-api workloads — including those built with amp-docker or amp-ballerina-buildpack (see allowedWorkflows, lines 12–17) — any agent that doesn't happen to have /workspace/main.py will CrashLoopBackOff because exec /cnb/process/web never runs.

🛡️ Proposed fix — add an existence guard at the top of the patch script
-                      p = Path('/workspace/main.py')
-                      text = p.read_text()
+                      p = Path('/workspace/main.py')
+                      if not p.exists():
+                          print("startup hotfix: /workspace/main.py not found, skipping")
+                          exit(0)
+                      text = p.read_text()
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@deployments/helm-charts/wso2-amp-platform-resources-extension/templates/component-types/agent-api.yaml`
around lines 162 - 177, The startup hotfix script calls p.read_text() on p =
Path('/workspace/main.py') without checking existence, which causes a
FileNotFoundError for agents that don't include that file; update the script
around the p = Path('/workspace/main.py') / p.read_text() usage to first check
p.exists() (or wrap read_text() in a try/except FileNotFoundError) and skip the
patch/early-return (and print a short message) when the file is absent so the
component doesn't crash on startup.

Comment on lines +168 to +177
if old in text:
text = text.replace(old, new, 1)

old2 = """# Route to chat with OpenAI\n@app.post(\"/chat/\")\ndef ask_openai(question: Question):\n try:\n response = client.chat.completions.create(\n model=\"gpt-4o\",\n messages=[{\"role\": \"user\", \"content\": question.prompt}]\n )\n result = response.choices[0].message.content\n\n # Store chat history in database\n db = SessionLocal()\n db.add(QueryHistory(question=question.prompt, response=result))\n db.commit()\n\n return {\"response\": result}\n except Exception as e:\n raise HTTPException(status_code=500, detail=str(e))\n"""
new2 = """# Route to chat with OpenAI\n@app.post(\"/chat/\")\ndef ask_openai(question: Question):\n try:\n user_prompt = question.message or question.prompt\n if not user_prompt:\n raise HTTPException(status_code=422, detail=\"message or prompt is required\")\n\n response = client.chat.completions.create(\n model=\"gpt-4o\",\n messages=[{\"role\": \"user\", \"content\": user_prompt}]\n )\n result = response.choices[0].message.content\n\n # Store chat history in database\n db = SessionLocal()\n db.add(QueryHistory(question=user_prompt, response=result))\n db.commit()\n\n return {\"response\": result}\n except HTTPException:\n raise\n except Exception as e:\n raise HTTPException(status_code=500, detail=str(e))\n"""
if old2 in text:
text = text.replace(old2, new2, 1)

p.write_text(text)
print("startup hotfix applied")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Major: print("startup hotfix applied") is unconditional — masks silent no-ops.

p.write_text(text) and print("startup hotfix applied") execute regardless of whether either if old in text: / if old2 in text: branch matched. If the source code changes and neither pattern matches, the script silently does nothing but still reports success, making it invisible in logs that the hotfix was never applied.

🛡️ Proposed fix — conditional reporting
+                      applied = False
                       if old in text:
                           text = text.replace(old, new, 1)
+                          applied = True

                       ...

                       if old2 in text:
                           text = text.replace(old2, new2, 1)
+                          applied = True

                       p.write_text(text)
-                      print("startup hotfix applied")
+                      if applied:
+                          print("startup hotfix applied")
+                      else:
+                          print("startup hotfix: no patterns matched — source may have changed")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if old in text:
text = text.replace(old, new, 1)
old2 = """# Route to chat with OpenAI\n@app.post(\"/chat/\")\ndef ask_openai(question: Question):\n try:\n response = client.chat.completions.create(\n model=\"gpt-4o\",\n messages=[{\"role\": \"user\", \"content\": question.prompt}]\n )\n result = response.choices[0].message.content\n\n # Store chat history in database\n db = SessionLocal()\n db.add(QueryHistory(question=question.prompt, response=result))\n db.commit()\n\n return {\"response\": result}\n except Exception as e:\n raise HTTPException(status_code=500, detail=str(e))\n"""
new2 = """# Route to chat with OpenAI\n@app.post(\"/chat/\")\ndef ask_openai(question: Question):\n try:\n user_prompt = question.message or question.prompt\n if not user_prompt:\n raise HTTPException(status_code=422, detail=\"message or prompt is required\")\n\n response = client.chat.completions.create(\n model=\"gpt-4o\",\n messages=[{\"role\": \"user\", \"content\": user_prompt}]\n )\n result = response.choices[0].message.content\n\n # Store chat history in database\n db = SessionLocal()\n db.add(QueryHistory(question=user_prompt, response=result))\n db.commit()\n\n return {\"response\": result}\n except HTTPException:\n raise\n except Exception as e:\n raise HTTPException(status_code=500, detail=str(e))\n"""
if old2 in text:
text = text.replace(old2, new2, 1)
p.write_text(text)
print("startup hotfix applied")
applied = False
if old in text:
text = text.replace(old, new, 1)
applied = True
old2 = """# Route to chat with OpenAI\n@app.post(\"/chat/\")\ndef ask_openai(question: Question):\n try:\n response = client.chat.completions.create(\n model=\"gpt-4o\",\n messages=[{\"role\": \"user\", \"content\": question.prompt}]\n )\n result = response.choices[0].message.content\n\n # Store chat history in database\n db = SessionLocal()\n db.add(QueryHistory(question=question.prompt, response=result))\n db.commit()\n\n return {\"response\": result}\n except Exception as e:\n raise HTTPException(status_code=500, detail=str(e))\n"""
new2 = """# Route to chat with OpenAI\n@app.post(\"/chat/\")\ndef ask_openai(question: Question):\n try:\n user_prompt = question.message or question.prompt\n if not user_prompt:\n raise HTTPException(status_code=422, detail=\"message or prompt is required\")\n\n response = client.chat.completions.create(\n model=\"gpt-4o\",\n messages=[{\"role\": \"user\", \"content\": user_prompt}]\n )\n result = response.choices[0].message.content\n\n # Store chat history in database\n db = SessionLocal()\n db.add(QueryHistory(question=user_prompt, response=result))\n db.commit()\n\n return {\"response\": result}\n except HTTPException:\n raise\n except Exception as e:\n raise HTTPException(status_code=500, detail=str(e))\n"""
if old2 in text:
text = text.replace(old2, new2, 1)
applied = True
p.write_text(text)
if applied:
print("startup hotfix applied")
else:
print("startup hotfix: no patterns matched — source may have changed")
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@deployments/helm-charts/wso2-amp-platform-resources-extension/templates/component-types/agent-api.yaml`
around lines 168 - 177, The script unconditionally calls p.write_text(text) and
print("startup hotfix applied") even when no replacement occurred; modify the
flow to detect whether any replacement happened (e.g., track a boolean changed
flag or compare original_text vs text) after attempting both if old in text and
if old2 in text replacements, and only call p.write_text(text) and
print("startup hotfix applied") when changed is true; otherwise skip
writing/printing (or emit a distinct message) so p.write_text, print and the
variables old, old2, new, new2, text reflect actual changes.

p.write_text(text)
print("startup hotfix applied")
PY
/layers/google.python.runtime/python/bin/python3 /tmp/amp_chat_hotfix.py
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Major: hardcoded GCP Buildpack interpreter path breaks non-GCP agent-api deployments.

/layers/google.python.runtime/python/bin/python3 only exists inside containers built with the Google Cloud Python Buildpack. The allowedWorkflows list on this same ClusterComponentType includes amp-docker and amp-ballerina-buildpack, neither of which will have this interpreter at that path. The python3 invocation will fail before any existence check in the script can run, again preventing exec /cnb/process/web from executing.

Consider falling back to a PATH-resolved interpreter so the script is a no-op for non-matching containers:

🛡️ Proposed fix — use PATH-resolved python3 with fallback
-                      /layers/google.python.runtime/python/bin/python3 /tmp/amp_chat_hotfix.py
+                      PYTHON3=$(command -v python3 2>/dev/null || echo /layers/google.python.runtime/python/bin/python3)
+                      "$PYTHON3" /tmp/amp_chat_hotfix.py

Note that this alone is still insufficient if /workspace/main.py is absent (see the preceding comment).

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/layers/google.python.runtime/python/bin/python3 /tmp/amp_chat_hotfix.py
PYTHON3=$(command -v python3 2>/dev/null || echo /layers/google.python.runtime/python/bin/python3)
"$PYTHON3" /tmp/amp_chat_hotfix.py
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@deployments/helm-charts/wso2-amp-platform-resources-extension/templates/component-types/agent-api.yaml`
at line 179, The container command hardcodes the GCP Buildpack interpreter path
"/layers/google.python.runtime/python/bin/python3" which will fail for non-GCP
workflows listed in allowedWorkflows (e.g., amp-docker,
amp-ballerina-buildpack); replace that hardcoded path with a PATH-resolved
fallback so non-GCP containers simply skip/noop: change the command that runs
"/tmp/amp_chat_hotfix.py" to invoke python via a PATH resolution (e.g., prefer
`python3` if available, fall back to `python` or skip) or wrap invocation in a
shell that checks for a python interpreter before executing the script, ensuring
exec /cnb/process/web still runs when no suitable interpreter exists.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants