Skip to content

feat(Prompt Iteration): Move processing to Celery#1023

Merged
AkhileshNegi merged 7 commits into
mainfrom
hotfix/prompt-iteration
Jul 17, 2026
Merged

feat(Prompt Iteration): Move processing to Celery#1023
AkhileshNegi merged 7 commits into
mainfrom
hotfix/prompt-iteration

Conversation

@AkhileshNegi

@AkhileshNegi AkhileshNegi commented Jul 9, 2026

Copy link
Copy Markdown
Collaborator

Issue

Closes #1018

Summary

  • Prompt improvement is now processed asynchronously, returning a job ID immediately.
  • Added status polling to track pending, processing, successful, or failed jobs.
  • Successful jobs provide the newly generated prompt configuration; failures include an error message.
  • Updated API and evaluation documentation with the asynchronous workflow, statuses, validations, and responses.

Checklist

Before submitting a pull request, please ensure that you mark these task.

  • Ran fastapi run --reload app/main.py or docker compose up in the repository root and test.
  • If you've fixed a bug or added code that is tested and has test cases.

@AkhileshNegi AkhileshNegi self-assigned this Jul 9, 2026
@github-actions github-actions Bot changed the title Prompt Iteration: Moving to celery feat(prompt): Move processing to Celery Jul 9, 2026
@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown

OpenAPI changes   🔴 2 breaking changes

Caution

Downstream consumers may need an update before merging.

Breaking changes  ·  2
Method Path Change
🔴 POST /api/v1/evaluations/{evaluation_id}/improve-prompt added required request body
🔴 POST /api/v1/evaluations/{evaluation_id}/improve-prompt removed the success response with the status 201
Full changelog  ·  3
Method Path Change
🔴 POST /api/v1/evaluations/{evaluation_id}/improve-prompt added required request body
🔴 POST /api/v1/evaluations/{evaluation_id}/improve-prompt removed the success response with the status 201
🟢 POST /api/v1/evaluations/{evaluation_id}/improve-prompt added the success response with the status 202

maind114980a · generated by oasdiff

@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Prompt improvement now validates completed evaluations, returns 202 Accepted with a job ID, executes trace and Claude processing in Celery, persists the next config version, and reports success or failure through a signed, best-effort callback.

Changes

Asynchronous prompt improvement

Layer / File(s) Summary
Job contracts and persistence
backend/app/models/evaluation.py, backend/app/models/job.py, backend/app/services/evaluations/__init__.py, backend/app/alembic/versions/074_add_prompt_improvement_jobtype.py
Adds request and callback payload models, the PROMPT_IMPROVEMENT job type, service exports, and the PostgreSQL enum migration.
Validation and job enqueueing
backend/app/api/routes/evaluations/evaluation.py, backend/app/services/evaluations/prompt_improvement.py, backend/app/celery/utils.py, backend/app/celery/tasks/job_execution.py
Validates evaluation prerequisites and callback URLs, creates and enqueues jobs, and returns immediate 202 job metadata.
Worker execution and callback delivery
backend/app/services/evaluations/prompt_improvement.py
Loads traces, invokes Claude, updates only prompt instructions, persists config versions, records job outcomes, sends callbacks, and supports successful-job redelivery.
Async workflow test coverage
backend/app/tests/api/routes/test_improve_prompt.py
Covers validation, enqueueing, callback URL failures, enqueue errors, worker setup, and removal of the legacy polling route.
Worker outcomes and workflow documentation
backend/app/tests/api/routes/test_improve_prompt.py, backend/app/api/docs/evaluation/improve_prompt.md, docs/wiki/domain-map.md, docs/wiki/modules/evaluations.md
Tests success, failure, timeout, callback, config-version, and idempotency behavior while documenting the asynchronous callback lifecycle.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant EvaluationAPI
  participant PromptImprovementService
  participant Celery
  participant ObjectStorage
  participant Claude
  participant Database
  participant CallbackURL
  Client->>EvaluationAPI: POST improve-prompt with callback_url
  EvaluationAPI->>PromptImprovementService: validate and start job
  PromptImprovementService->>Celery: enqueue run_prompt_improvement
  EvaluationAPI-->>Client: return 202 with job_id
  Celery->>ObjectStorage: load score traces
  Celery->>Claude: draft improved instructions
  Celery->>Database: persist config version and job status
  Celery->>CallbackURL: POST success or failure APIResponse
Loading

Possibly related issues

  • ProjectTech4DevAI/kaapi-frontend issue 248 — Addresses frontend handling for the asynchronous improve-prompt job and job_id contract.

Possibly related PRs

Suggested labels: enhancement

Suggested reviewers: prajna1999, vprashrex

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 7.41% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The PR moves prompt improvement off the request path into Celery and returns immediately with a job handle, matching #1018.
Out of Scope Changes check ✅ Passed The added models, task wiring, route changes, docs, tests, and migration all support the async prompt-improvement workflow.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main change: prompt improvement processing was moved to Celery for asynchronous execution.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch hotfix/prompt-iteration

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.

@codecov

codecov Bot commented Jul 9, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 93.76771% with 22 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...end/app/services/evaluations/prompt_improvement.py 85.57% 15 Missing ⚠️
backend/app/celery/utils.py 20.00% 4 Missing ⚠️
backend/app/celery/tasks/job_execution.py 50.00% 3 Missing ⚠️

📢 Thoughts on this report? Let us know!

@AkhileshNegi
AkhileshNegi marked this pull request as ready for review July 14, 2026 10:24

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 7

🤖 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 `@backend/app/api/routes/evaluations/evaluation.py`:
- Around line 269-289: Update the job lookup and successful-result resolution
around JobCrud.get and get_evaluation_run_by_id to validate the job belongs to
the requested evaluation_id and has type PROMPT_IMPROVEMENT, persisting those
fields when the job is created. Resolve the config version from the persisted
config_version_id in job.meta instead of combining the caller evaluation_id with
a metadata version number, while preserving the existing not-found and
successful response behavior.

In `@backend/app/celery/tasks/job_execution.py`:
- Around line 249-253: Update run_prompt_improvement by adding explicit type
hints for self, **kwargs, and a dict return value, consistent with the task’s
existing conventions. Replace the literal priority=6 with a descriptive
fast-evaluation priority constant or the appropriate settings value, preserving
the task’s current queue and priority behavior.

In `@backend/app/celery/utils.py`:
- Around line 183-186: Update start_prompt_improvement to annotate kwargs with
an appropriate mapping value type such as Any, and replace the raw trace_id
default "N/A" with a named module-level constant such as DEFAULT_TRACE_ID.
Preserve the existing function behavior and use the constant in the signature.

In `@backend/app/services/evaluations/prompt_improvement.py`:
- Around line 211-218: In backend/app/services/evaluations/prompt_improvement.py
lines 211-218, update execute_prompt_improvement to replace **kwargs with an
explicitly typed task_id parameter and return the appropriate typed result
model. In backend/app/tests/api/routes/test_improve_prompt.py lines 101-107,
replace broad Any and bare-container annotations throughout the changed helpers
and test cases with concrete fixture, domain, and sentinel types; ensure every
affected parameter and return value has a narrowed type hint.
- Around line 187-199: Update the failure handling in the prompt-improvement job
enqueue paths, including the block around JobCrud.update, so job.error_message
never contains raw exc text. Keep exc and exc_info=True in logger.error for
diagnostics, but persist a stable sanitized client-facing error code or message
instead of interpolating exc; apply the same change to the other referenced
failure path.
- Around line 241-250: The execute_prompt_improvement flow currently checks
SUCCESS non-atomically, allowing concurrent deliveries or retries after a crash
to create duplicate versions. Replace the check/update sequence around
job_crud.get and job_crud.update with an atomic job claim or lease, and make
version creation plus the SUCCESS completion update transactional or keyed by
the job for idempotency; apply the same coordination to the later
create_or_raise flow referenced around lines 301-322.

In `@backend/app/tests/api/routes/test_improve_prompt.py`:
- Line 24: Update the typing import in test_improve_prompt.py to import Iterator
from collections.abc instead of typing, while keeping Any sourced from typing.
🪄 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: 0336024b-43c0-44b2-a8db-6376ff94356e

📥 Commits

Reviewing files that changed from the base of the PR and between 19b74b7 and e8e441b.

📒 Files selected for processing (13)
  • backend/app/alembic/versions/073_add_prompt_improvement_jobtype.py
  • backend/app/api/docs/evaluation/get_improve_prompt_status.md
  • backend/app/api/docs/evaluation/improve_prompt.md
  • backend/app/api/routes/evaluations/evaluation.py
  • backend/app/celery/tasks/job_execution.py
  • backend/app/celery/utils.py
  • backend/app/models/evaluation.py
  • backend/app/models/job.py
  • backend/app/services/evaluations/__init__.py
  • backend/app/services/evaluations/prompt_improvement.py
  • backend/app/tests/api/routes/test_improve_prompt.py
  • docs/wiki/domain-map.md
  • docs/wiki/modules/evaluations.md

Comment thread backend/app/api/routes/evaluations/evaluation.py Outdated
Comment on lines +249 to +253
# Priority 6 (fast-eval tier): user-blocking interactive prompt iteration in the
# evaluation domain, above default batch work but below core LLM call/chain jobs.
@celery_app.task(bind=True, queue="default", priority=6)
@gevent_timeout(settings.CELERY_TASK_SOFT_TIME_LIMIT, "run_prompt_improvement")
def run_prompt_improvement(self, project_id: int, job_id: str, trace_id: str, **kwargs):

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Add missing type hints and extract magic values.

As per coding guidelines, every function parameter and return value must have a type hint, and magic values must be extracted to constants.

  • The run_prompt_improvement function is missing type hints for self, **kwargs, and its return value (-> dict).
  • priority=6 is a magic number. Since the comment identifies it as the "fast-eval tier", it should be extracted to a descriptive constant or loaded from settings.
💡 Proposed fix (example)
 # Priority 6 (fast-eval tier): user-blocking interactive prompt iteration in the
 # evaluation domain, above default batch work but below core LLM call/chain jobs.
-@celery_app.task(bind=True, queue="default", priority=6)
+FAST_EVAL_PRIORITY = 6
+
+@celery_app.task(bind=True, queue="default", priority=FAST_EVAL_PRIORITY)
 `@gevent_timeout`(settings.CELERY_TASK_SOFT_TIME_LIMIT, "run_prompt_improvement")
-def run_prompt_improvement(self, project_id: int, job_id: str, trace_id: str, **kwargs):
+def run_prompt_improvement(self: Any, project_id: int, job_id: str, trace_id: str, **kwargs: Any) -> dict:
     from app.services.evaluations.prompt_improvement import execute_prompt_improvement
📝 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
# Priority 6 (fast-eval tier): user-blocking interactive prompt iteration in the
# evaluation domain, above default batch work but below core LLM call/chain jobs.
@celery_app.task(bind=True, queue="default", priority=6)
@gevent_timeout(settings.CELERY_TASK_SOFT_TIME_LIMIT, "run_prompt_improvement")
def run_prompt_improvement(self, project_id: int, job_id: str, trace_id: str, **kwargs):
# Priority 6 (fast-eval tier): user-blocking interactive prompt iteration in the
# evaluation domain, above default batch work but below core LLM call/chain jobs.
FAST_EVAL_PRIORITY = 6
`@celery_app.task`(bind=True, queue="default", priority=FAST_EVAL_PRIORITY)
`@gevent_timeout`(settings.CELERY_TASK_SOFT_TIME_LIMIT, "run_prompt_improvement")
def run_prompt_improvement(self: Any, project_id: int, job_id: str, trace_id: str, **kwargs: Any) -> dict:
🤖 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 `@backend/app/celery/tasks/job_execution.py` around lines 249 - 253, Update
run_prompt_improvement by adding explicit type hints for self, **kwargs, and a
dict return value, consistent with the task’s existing conventions. Replace the
literal priority=6 with a descriptive fast-evaluation priority constant or the
appropriate settings value, preserving the task’s current queue and priority
behavior.

Source: Coding guidelines

Comment on lines +183 to +186
def start_prompt_improvement(
project_id: int, job_id: str, trace_id: str = "N/A", **kwargs
) -> str:
from app.celery.tasks.job_execution import run_prompt_improvement

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Add type hints for kwargs and avoid magic values.

As per coding guidelines, every function parameter must have a type hint, and magic values should be extracted into constants.

  • **kwargs is missing a type hint (e.g., **kwargs: Any).
  • The default value "N/A" is a magic string. Consider defining a constant (e.g., DEFAULT_TRACE_ID = "N/A") instead of using a raw literal.
💡 Proposed fix (example)
+DEFAULT_TRACE_ID = "N/A"
+
 def start_prompt_improvement(
-    project_id: int, job_id: str, trace_id: str = "N/A", **kwargs
+    project_id: int, job_id: str, trace_id: str = DEFAULT_TRACE_ID, **kwargs: Any
 ) -> str:
📝 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
def start_prompt_improvement(
project_id: int, job_id: str, trace_id: str = "N/A", **kwargs
) -> str:
from app.celery.tasks.job_execution import run_prompt_improvement
DEFAULT_TRACE_ID = "N/A"
def start_prompt_improvement(
project_id: int, job_id: str, trace_id: str = DEFAULT_TRACE_ID, **kwargs: Any
) -> str:
from app.celery.tasks.job_execution import run_prompt_improvement
🤖 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 `@backend/app/celery/utils.py` around lines 183 - 186, Update
start_prompt_improvement to annotate kwargs with an appropriate mapping value
type such as Any, and replace the raw trace_id default "N/A" with a named
module-level constant such as DEFAULT_TRACE_ID. Preserve the existing function
behavior and use the constant in the signature.

Source: Coding guidelines

Comment on lines +187 to +199
except Exception as exc:
logger.error(
f"[start_prompt_improvement_job] Failed to enqueue | job_id={job.id} "
f"evaluation_id={evaluation_id} | {exc}",
exc_info=True,
)
JobCrud(session=session).update(
job.id,
JobUpdate(
status=JobStatus.FAILED,
error_message=f"Failed to queue prompt improvement: {exc}",
),
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Do not persist raw exception text in client-visible job errors.

Both paths store str(exc), while the polling endpoint returns job.error_message verbatim. Database, broker, storage, or SDK exceptions can therefore expose internal details. Log the original exception, but persist a stable sanitized error code/message.

Also applies to: 348-360

🤖 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 `@backend/app/services/evaluations/prompt_improvement.py` around lines 187 -
199, Update the failure handling in the prompt-improvement job enqueue paths,
including the block around JobCrud.update, so job.error_message never contains
raw exc text. Keep exc and exc_info=True in logger.error for diagnostics, but
persist a stable sanitized client-facing error code or message instead of
interpolating exc; apply the same change to the other referenced failure path.

Comment on lines +211 to +218
def execute_prompt_improvement(
*,
project_id: int,
job_id: str,
organization_id: int,
evaluation_id: int,
**kwargs,
) -> dict:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Narrow the new async-flow type contracts.

  • backend/app/services/evaluations/prompt_improvement.py#L211-L218: replace **kwargs with an explicit typed task_id and return a typed result model.
  • backend/app/tests/api/routes/test_improve_prompt.py#L101-L107: replace new broad Any/bare-container annotations throughout the changed helpers and test cases with concrete fixture, domain, and sentinel types.

As per coding guidelines, every function parameter and return value must have narrowed type hints.

📍 Affects 2 files
  • backend/app/services/evaluations/prompt_improvement.py#L211-L218 (this comment)
  • backend/app/tests/api/routes/test_improve_prompt.py#L101-L107
🤖 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 `@backend/app/services/evaluations/prompt_improvement.py` around lines 211 -
218, In backend/app/services/evaluations/prompt_improvement.py lines 211-218,
update execute_prompt_improvement to replace **kwargs with an explicitly typed
task_id parameter and return the appropriate typed result model. In
backend/app/tests/api/routes/test_improve_prompt.py lines 101-107, replace broad
Any and bare-container annotations throughout the changed helpers and test cases
with concrete fixture, domain, and sentinel types; ensure every affected
parameter and return value has a narrowed type hint.

Source: Coding guidelines

Comment on lines +241 to +250
existing = job_crud.get(job_id=job_uuid, project_id=project_id)
if existing and existing.status == JobStatus.SUCCESS:
logger.info(
f"[execute_prompt_improvement] Redelivery of completed job, skipping | "
f"job_id={job_id}"
)
return {"success": True, **(existing.meta or {})}

job_crud.update(
job_uuid, JobUpdate(status=JobStatus.PROCESSING, task_id=task_id)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Make version creation and job completion idempotent atomically.

The SUCCESS check only protects sequential redeliveries. Concurrent deliveries can both pass it, and a crash after create_or_raise() but before the SUCCESS update causes a retry to mint another version. Use an atomic job claim/lease plus a transaction or job-based idempotency key for version creation.

Also applies to: 301-322

🤖 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 `@backend/app/services/evaluations/prompt_improvement.py` around lines 241 -
250, The execute_prompt_improvement flow currently checks SUCCESS
non-atomically, allowing concurrent deliveries or retries after a crash to
create duplicate versions. Replace the check/update sequence around job_crud.get
and job_crud.update with an atomic job claim or lease, and make version creation
plus the SUCCESS completion update transactional or keyed by the job for
idempotency; apply the same coordination to the later create_or_raise flow
referenced around lines 301-322.

import contextlib
import json
from contextlib import ExitStack
from typing import Any, Iterator

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

ruff check backend/app/tests/api/routes/test_improve_prompt.py --select UP035

Repository: ProjectTech4DevAI/kaapi-backend

Length of output: 794


Import Iterator from collections.abc.

Proposed fix
+from collections.abc import Iterator
-from typing import Any, Iterator
+from typing import Any
📝 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
from typing import Any, Iterator
from collections.abc import Iterator
from typing import Any
🧰 Tools
🪛 Ruff (0.15.21)

[warning] 24-24: Import from collections.abc instead: Iterator

Import from collections.abc

(UP035)

🤖 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 `@backend/app/tests/api/routes/test_improve_prompt.py` at line 24, Update the
typing import in test_improve_prompt.py to import Iterator from collections.abc
instead of typing, while keeping Any sourced from typing.

Source: Linters/SAST tools

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
backend/app/tests/api/routes/test_improve_prompt.py (1)

144-145: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Exercise the signed-callback path.

_worker_env always returns None for the webhook secret, so these assertions cannot detect regressions that make callbacks unsigned. Use a non-empty test secret and verify that send_callback receives the signing input or resulting signature metadata.

Also applies to: 636-659

🤖 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 `@backend/app/tests/api/routes/test_improve_prompt.py` around lines 144 - 145,
Update the test setup around _SERVICE.get_webhook_secret to return a non-empty
secret, then assert that send_callback receives the expected signing input or
signature metadata. Apply the same signed-callback assertions to the related
coverage in the additional range, while preserving the existing callback
behavior checks.
🤖 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 `@backend/app/api/docs/evaluation/improve_prompt.md`:
- Line 17: Update the callback contract in
backend/app/api/docs/evaluation/improve_prompt.md:17-17 and
docs/wiki/modules/evaluations.md:31-31 to describe at-least-once delivery rather
than a single best-effort attempt, explicitly noting that Celery redelivery may
produce duplicate callbacks and clients must deduplicate by job_id. Preserve the
existing statement that config_version remains persisted and recoverable
regardless of callback outcome.

---

Nitpick comments:
In `@backend/app/tests/api/routes/test_improve_prompt.py`:
- Around line 144-145: Update the test setup around _SERVICE.get_webhook_secret
to return a non-empty secret, then assert that send_callback receives the
expected signing input or signature metadata. Apply the same signed-callback
assertions to the related coverage in the additional range, while preserving the
existing callback behavior checks.
🪄 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: cdd50c8f-f07d-4ebc-82ed-0bf26360ae6f

📥 Commits

Reviewing files that changed from the base of the PR and between e8e441b and de1d463.

📒 Files selected for processing (7)
  • backend/app/alembic/versions/074_add_prompt_improvement_jobtype.py
  • backend/app/api/docs/evaluation/improve_prompt.md
  • backend/app/api/routes/evaluations/evaluation.py
  • backend/app/models/evaluation.py
  • backend/app/services/evaluations/prompt_improvement.py
  • backend/app/tests/api/routes/test_improve_prompt.py
  • docs/wiki/modules/evaluations.md
🚧 Files skipped from review as they are similar to previous changes (2)
  • backend/app/models/evaluation.py
  • backend/app/services/evaluations/prompt_improvement.py


**Callback delivery:**

Once the worker finishes (success or failure), it POSTs a single JSON body to `callback_url`. Delivery is **best-effort, single-attempt** — there is no retry. The `config_version` is persisted regardless of callback outcome and remains recoverable from the configuration's version list, so a failed callback loses the notification, not the work.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Align both documents with the worker’s at-least-once callback behavior.

Celery redelivery can cause the same successful job callback to be sent again, so clients must tolerate duplicates and deduplicate by job_id.

  • backend/app/api/docs/evaluation/improve_prompt.md#L17-L17: replace “single-attempt”/“no retry” with explicit at-least-once semantics and duplicate-callback guidance.
  • docs/wiki/modules/evaluations.md#L31-L31: replace “single best-effort callback” with the same at-least-once contract.
📍 Affects 2 files
  • backend/app/api/docs/evaluation/improve_prompt.md#L17-L17 (this comment)
  • docs/wiki/modules/evaluations.md#L31-L31
🤖 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 `@backend/app/api/docs/evaluation/improve_prompt.md` at line 17, Update the
callback contract in backend/app/api/docs/evaluation/improve_prompt.md:17-17 and
docs/wiki/modules/evaluations.md:31-31 to describe at-least-once delivery rather
than a single best-effort attempt, explicitly noting that Celery redelivery may
produce duplicate callbacks and clients must deduplicate by job_id. Preserve the
existing statement that config_version remains persisted and recoverable
regardless of callback outcome.

@Ayush8923 Ayush8923 added the breaking-change-approved Reviewer-acknowledged API breaking change label Jul 17, 2026
@AkhileshNegi
AkhileshNegi requested a review from Ayush8923 July 17, 2026 10:38
@AkhileshNegi AkhileshNegi changed the title feat(prompt): Move processing to Celery feat(Prompt Iteration): Move processing to Celery Jul 17, 2026
@AkhileshNegi
AkhileshNegi merged commit ff46094 into main Jul 17, 2026
4 of 5 checks passed
@AkhileshNegi
AkhileshNegi deleted the hotfix/prompt-iteration branch July 17, 2026 10:56
@github-actions

Copy link
Copy Markdown

🎉 This PR is included in version 1.4.0-main.5 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Prompt Iteration: Asynchronous Anthropic call

2 participants