Skip to content

BZ-4797: feat: template level service callback url for inbound and outbound calls - #919

Open
adarshba wants to merge 1 commit into
juspay:releasefrom
adarshba:BZ-4797-template-level-reporting-webhook-url-for-inbound-and-outbound-calls
Open

BZ-4797: feat: template level service callback url for inbound and outbound calls#919
adarshba wants to merge 1 commit into
juspay:releasefrom
adarshba:BZ-4797-template-level-reporting-webhook-url-for-inbound-and-outbound-calls

Conversation

@adarshba

@adarshba adarshba commented Jul 17, 2026

Copy link
Copy Markdown

Ticket

https://plane.breezehq.dev/breeze/browse/BZ-4797

Impacted Areas

  • Template Configuration — merchants set a service_callback (url, max_attempts) directly on the template's configurations
  • Outbound Calls — call summary/completion, pre-check-failure, and no-answer callbacks are always sent to the active template's service_callback.url
  • Inbound Calls — same template-level callback fires for inbound calls; there is no per-request override
  • Lead Push API — the legacy per-request reporting_webhook_url field has been removed from PushLeadRequest; it is silently ignored if a caller still sends it

What is done?

Added service_callback: Optional[ServiceCallbackConfig] (url, max_attempts) on the template's configurations in template/types.py. callbacks/service_callback.py resolves the webhook purely from context.configurations.service_callback at send-time for completion, pre-check-failure, and no-answer callbacks — for both inbound and outbound calls. The per-request reporting_webhook_url field has been removed from PushLeadRequest (types/models.py) and push_lead_handler no longer reads or forwards it.

Why is it done?

Previously, reporting_webhook_url had to be passed explicitly on every outbound lead push request, and there was no equivalent mechanism for inbound calls (no API caller exists at call time). Merchants now configure the callback once on the template and it applies uniformly to all calls, inbound and outbound, removing the need for a per-call/per-request value entirely.

How to test it?

  1. Create or update a template — set configurations.service_callback.url (e.g. a webhook.site URL)
  2. Push an outbound lead for that template — the call summary should be POSTed to the template's service_callback.url after the call ends
  3. Receive an inbound call on a number linked to that template — after the call ends, confirm the call summary is POSTed to the template's service_callback.url
  4. If multiple templates are on the same number (IVR), select one via IVR — confirm the selected template's service_callback.url receives the call summary
  5. Confirm pushing a lead with a legacy reporting_webhook_url in the request body has no effect (field is ignored, no error)

Priority

high

Environment Variables

No new environment variables.

Dev Proof

  1. Queries:
  • SELECT id, template, payload FROM lead_call_tracker WHERE id = '0b588e5e-019d-4fad-aa0a-dd3f22b5d866';
  • SELECT id, template, call_direction, payload FROM lead_call_tracker WHERE call_id = 'test-inbound-call-001';
  1. Screens:

Copilot AI review requested due to automatic review settings July 17, 2026 10:41
@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 45d9cbfe-f562-4358-9d0b-6b18ece2615f

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Walkthrough

Changes

Reporting webhook configuration

Layer / File(s) Summary
Template configuration and lead payloads
app/ai/voice/agents/breeze_buddy/template/types.py, app/ai/voice/agents/breeze_buddy/template/field_reference.json, app/api/routers/breeze_buddy/leads/handlers.py, app/api/routers/breeze_buddy/telephony/answer/handlers.py
Adds optional template-level webhook configuration and propagates it into inbound and push-lead payloads.
Lead tracker persistence
app/database/accessor/breeze_buddy/lead_call_tracker.py, app/database/queries/breeze_buddy/lead_call_tracker.py
Extends lead template updates and conditionally merges the webhook URL into stored payload JSON.
IVR existing-lead update
app/ai/voice/agents/breeze_buddy/ivr/selection.py
Passes the selected template’s webhook URL when updating an existing lead during deferred inbound handling.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Template
  participant IVRSelection
  participant LeadTrackerAccessor
  participant DatabaseQuery
  Template->>IVRSelection: resolve configurations.reporting_webhook_url
  IVRSelection->>LeadTrackerAccessor: update existing lead with webhook URL
  LeadTrackerAccessor->>DatabaseQuery: update lead template
  DatabaseQuery->>DatabaseQuery: merge webhook URL into payload JSON
Loading

Possibly related PRs

Suggested reviewers: copilot

Poem

I’m a rabbit with a webhook to send,
Through template fields from start to end.
Leads carry the URL, neat and bright,
IVR updates keep it in sight.
JSON stores the trail with care—
Hop, hop, reports are there! 🐇

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the addition of a template-level callback URL for inbound and outbound calls.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

Copilot AI 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.

Pull request overview

Adds support for configuring a reporting_webhook_url at the template level so call-summary reporting can be applied automatically to outbound and inbound calls, with template configuration taking precedence over per-request values.

Changes:

  • Introduces reporting_webhook_url on the template ConfigurationModel and documents it in the field reference.
  • For outbound lead pushes, resolves the effective webhook URL by preferring template.configurations.reporting_webhook_url over the request field.
  • For inbound leads, injects the template webhook URL into the lead payload at answer-time, and threads webhook updates into the lead-template update query.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
app/database/queries/breeze_buddy/lead_call_tracker.py Extends update_lead_template_query to optionally merge reporting_webhook_url into the lead payload via SQL.
app/database/accessor/breeze_buddy/lead_call_tracker.py Threads optional reporting_webhook_url through update_lead_template(...) into the query layer.
app/api/routers/breeze_buddy/telephony/answer/handlers.py Injects template webhook URL into inbound lead payload at lead creation time.
app/api/routers/breeze_buddy/leads/handlers.py Resolves outbound reporting webhook with template-level priority over request-level value.
app/ai/voice/agents/breeze_buddy/template/types.py Adds reporting_webhook_url to template configuration model.
app/ai/voice/agents/breeze_buddy/template/field_reference.json Documents the new reporting_webhook_url template configuration field.
app/ai/voice/agents/breeze_buddy/ivr/selection.py Passes selected template’s webhook URL into update_lead_template (currently only in a specific IVR blocked path).

Comment thread app/api/routers/breeze_buddy/telephony/answer/handlers.py Outdated
Comment thread app/ai/voice/agents/breeze_buddy/ivr/selection.py Outdated
Comment thread app/database/queries/breeze_buddy/lead_call_tracker.py Outdated
@adarshba
adarshba force-pushed the BZ-4797-template-level-reporting-webhook-url-for-inbound-and-outbound-calls branch from 74e1ec4 to 16216d1 Compare July 17, 2026 11:15
@adarshba
adarshba requested a review from Copilot July 17, 2026 12:21

Copilot AI 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.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.

Comment thread app/database/queries/breeze_buddy/lead_call_tracker.py Outdated
Comment thread app/database/queries/breeze_buddy/lead_call_tracker.py Outdated
Comment thread app/database/accessor/breeze_buddy/lead_call_tracker.py
@adarshba
adarshba force-pushed the BZ-4797-template-level-reporting-webhook-url-for-inbound-and-outbound-calls branch from 16216d1 to 9e49ad3 Compare July 17, 2026 12:39
@adarshba
adarshba requested a review from Copilot July 17, 2026 12:40

Copilot AI 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.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.

Comment thread app/ai/voice/agents/breeze_buddy/agent/__init__.py Outdated
Comment thread app/ai/voice/agents/breeze_buddy/ivr/selection.py Outdated
Comment thread app/database/accessor/breeze_buddy/lead_call_tracker.py Outdated
@adarshba
adarshba force-pushed the BZ-4797-template-level-reporting-webhook-url-for-inbound-and-outbound-calls branch from 9e49ad3 to ea5185c Compare July 17, 2026 14:56
@adarshba
adarshba requested a review from Copilot July 17, 2026 14:57

Copilot AI 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.

Pull request overview

Copilot reviewed 12 out of 13 changed files in this pull request and generated 1 comment.

Comment thread app/ai/voice/agents/breeze_buddy/ivr/selection.py Outdated
@adarshba
adarshba force-pushed the BZ-4797-template-level-reporting-webhook-url-for-inbound-and-outbound-calls branch from ea5185c to d132402 Compare July 17, 2026 16:15
@adarshba
adarshba requested a review from Copilot July 17, 2026 16:15

Copilot AI 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.

Pull request overview

Copilot reviewed 12 out of 13 changed files in this pull request and generated 1 comment.

Comment thread app/ai/voice/agents/breeze_buddy/agent/transfer.py Outdated
@adarshba
adarshba force-pushed the BZ-4797-template-level-reporting-webhook-url-for-inbound-and-outbound-calls branch from d132402 to e3248be Compare July 17, 2026 16:35
@adarshba
adarshba requested a review from Copilot July 17, 2026 16:36

Copilot AI 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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@murdore

murdore commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

In apply_transfer (transfer.py:87), get_reporting_webhook_url(transfer.template) returns '' whenever the target template has no reporting_webhook_url configured (utils.py:33-39). But update_lead_template_query treats '' as an explicit "clear the field" signal, distinct from None which means "leave untouched" (per its own docstring and the - 'reporting_webhook_url' branch). So any warm transfer to a template without a configured webhook will silently wipe out a reporting_webhook_url that was already stored on the lead's payload — e.g. one set from the original per-request value or a prior template in the call. Consider having get_reporting_webhook_url return Optional[str] (None when unset) so callers that want "leave untouched" semantics at transfer time can actually express that, reserving '' for call sites that genuinely intend to clear it.

Comment thread app/database/accessor/breeze_buddy/lead_call_tracker.py Outdated
Comment thread app/database/queries/breeze_buddy/lead_call_tracker.py Outdated
Comment thread app/api/routers/breeze_buddy/telephony/answer/handlers.py Outdated
Comment thread app/ai/voice/agents/breeze_buddy/template/types.py Outdated
Comment thread app/ai/voice/agents/breeze_buddy/template/types.py Outdated
@adarshba
adarshba force-pushed the BZ-4797-template-level-reporting-webhook-url-for-inbound-and-outbound-calls branch from e3248be to ab5015d Compare July 24, 2026 06:24
@adarshba
adarshba force-pushed the BZ-4797-template-level-reporting-webhook-url-for-inbound-and-outbound-calls branch from ab5015d to d28d017 Compare July 24, 2026 07:34
@adarshba
adarshba requested a review from swaroopvarma1 July 24, 2026 10:21
@murdore

murdore commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Reviewed at d28d017f9. The branch was rewritten wholesale since the last round of comments (Copilot/@murdore/@swaroopvarma1 all reviewed earlier, now-unreachable commits — e3248bec, 9e49ad3d, ea5185c2, etc. — that had lead-payload-based reporting_webhook_url). That design is gone; the current commit resolves the callback purely from template.configurations.service_callback at send-time, which independently addresses the earlier "empty string clears payload" / "stale webhook after transfer" concerns. One new issue from the rewrite itself:

Per-request reporting_webhook_url is now silently dropped, not "retained as a deprecated fallback" as the PR description states.

PushLeadRequest no longer has the field at all:

     reseller_id: str
     merchant_id: Optional[str] = None
-    reporting_webhook_url: str | None = None
     execution_mode: Optional[ExecutionMode] = (

(app/ai/voice/agents/breeze_buddy/types/models.py)

and push_lead_handler no longer reads it:

-        # Prepare payload with reporting webhook URL
         lead_payload = {**req.payload}
-        if req.reporting_webhook_url:
-            lead_payload["reporting_webhook_url"] = req.reporting_webhook_url

(app/api/routers/breeze_buddy/leads/handlers.py)

PushLeadRequest has no model_config/extra="forbid" anywhere, so it keeps pydantic's default extra="ignore". That means any existing caller still sending reporting_webhook_url in the push-lead body (a previously documented request field — this PR's own diff removes the example of it from leads/__init__.py's docstring and from docs/BREEZE_BUDDY_ARCHITECTURE.md) will get a 200 with the field silently discarded — no webhook fires at all unless the merchant has separately configured configurations.service_callback on the template.

That contradicts the PR description's own stated design ("template-level webhook takes priority over the per-request webhook URL; request value is retained as a deprecated fallback") — there's no fallback path left in the code. Since this powers call-summary webhooks for existing merchant integrations, this reads as a silent breaking change for any caller that hasn't migrated to template-level service_callback yet, with nothing surfacing it (no error, no deprecation warning, no log).

Worth either implementing the fallback the description promises, or explicitly confirming no production caller still relies on the per-request field before this merges.

@adarshba adarshba changed the title BZ-4797: feat: template level reporting webhook url for inbound and outbound calls BZ-4797: feat: template level service callback url for inbound and outbound calls Aug 5, 2026
Comment thread app/ai/voice/agents/breeze_buddy/types/models.py
@adarshba
adarshba force-pushed the BZ-4797-template-level-reporting-webhook-url-for-inbound-and-outbound-calls branch 3 times, most recently from 4ccc705 to a47110e Compare August 10, 2026 07:45
- Add `configurations.service_callback` with `url` and `max_attempts`
- Send completion, pre-check-failure, and no-answer callbacks from the active template
- Remove lead-level `reporting_webhook_url` from lead push and callback resolution
- Add regression coverage and update callback documentation
@adarshba
adarshba force-pushed the BZ-4797-template-level-reporting-webhook-url-for-inbound-and-outbound-calls branch from a47110e to 6d38243 Compare August 11, 2026 08:35
@adarshba
adarshba requested a review from Dev-Bhumika03 August 11, 2026 10:59
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.

5 participants