Skip to content

Conversation

@HavenDV
Copy link
Contributor

@HavenDV HavenDV commented Aug 25, 2025

Summary by CodeRabbit

  • New Features

    • Introduced agent-scoped scheduled batch APIs to create, list, retrieve, update, and delete batches.
    • Added endpoints to view calls created by a batch and to list scheduled calls with status filtering.
    • Included pagination support for batch and scheduled call listings.
  • Refactor

    • Standardized webhook status values with a new WebhookStatus enum (normal, unhealthy); updated all references and removed the legacy status enum.
  • Chores

    • Expanded public API surface with new resources and data shapes for batching and scheduling.

@coderabbitai
Copy link

coderabbitai bot commented Aug 25, 2025

Walkthrough

Introduces agent-scoped scheduled batch APIs with list/create/retrieve/patch/delete endpoints and nested listings for created calls and scheduled calls (with status filtering). Adds schemas for ScheduledCallBatch, ScheduledCall, their paginated wrappers, and status enums. Replaces StatusEnum with WebhookStatusEnum in webhook models and removes the old enum.

Changes

Cohort / File(s) Summary
OpenAPI: Scheduled Batches & Webhook Status
src/libs/Ultravox/openapi.yaml
Added endpoints: /api/agents/{agent_id}/scheduled_batches (GET, POST), /.../scheduled_batches/{batch_id} (GET, PATCH, DELETE), /.../scheduled_batches/{batch_id}/created_calls (GET), /.../scheduled_batches/{batch_id}/scheduled_calls (GET with status filter). Added schemas: ScheduledCallBatch, PatchedScheduledCallBatch, ScheduledCall, PaginatedScheduledCallBatchList, PaginatedScheduledCallList, ScheduledCallStatusEnum. Replaced webhook StatusEnum with WebhookStatusEnum in Webhook and PatchedWebhook; removed old StatusEnum.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Client
  participant API as Ultravox API
  participant Scheduler as Scheduler/Batch Service
  participant Store as Data Store
  rect rgba(230,245,255,0.6)
    note over Client,API: Create a scheduled batch
    Client->>API: POST /agents/{agent_id}/scheduled_batches<br/>ScheduledCallBatch
    API->>Scheduler: validate + create batch
    Scheduler->>Store: persist batch + calls
    Store-->>Scheduler: ok
    Scheduler-->>API: ScheduledCallBatch
    API-->>Client: 201 ScheduledCallBatch
  end

  rect rgba(240,255,240,0.6)
    note over Client,API: List scheduled calls in a batch
    Client->>API: GET /.../scheduled_calls?status=FUTURE|PENDING|...
    API->>Store: query by batch_id [+ status]
    Store-->>API: PaginatedScheduledCallList
    API-->>Client: 200 PaginatedScheduledCallList
  end

  rect rgba(255,245,230,0.6)
    note over Client,API: Patch or pause a batch
    Client->>API: PATCH /.../scheduled_batches/{batch_id}<br/>PatchedScheduledCallBatch
    API->>Scheduler: apply partial updates
    Scheduler->>Store: update batch
    Store-->>Scheduler: ok
    Scheduler-->>API: ScheduledCallBatch
    API-->>Client: 200 ScheduledCallBatch
  end
Loading
sequenceDiagram
  autonumber
  participant System as System Health Monitor
  participant API as Ultravox API
  participant Store as Data Store
  note over System,API: Webhook status enum updated
  System->>API: GET/PUT Webhook
  API->>Store: read/write Webhook.status = normal|unhealthy
  Store-->>API: ok
  API-->>System: Webhook (WebhookStatusEnum)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

I twitch my ears at batches new,
Queued moonlight calls in orderly queue.
FUTURE hops to PENDING’s gate,
SUCCESS snacks, EXPIRED waits.
Webhooks thump: “normal!”—“unhealthy?”—boo!
I nose the YAML, crisp and true,
Then binky off to review. 🐇✨

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch bot/update-openapi_202508251818

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@github-actions github-actions bot merged commit 4da2fc2 into main Aug 25, 2025
2 of 3 checks passed
@github-actions github-actions bot deleted the bot/update-openapi_202508251818 branch August 25, 2025 18:18
@coderabbitai coderabbitai bot changed the title feat:@coderabbitai feat:Add agent-scoped scheduled batch APIs and update webhook status enum Aug 25, 2025
Copy link

@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: 2

🧹 Nitpick comments (7)
src/libs/Ultravox/openapi.yaml (7)

368-425: Align pagination parameter docs with existing endpoints

For consistency with other list endpoints (e.g., accounts invoices), please specify pageSize bounds and a default, and consider adding a minLength for cursor.

Proposed patch:

       - name: cursor
         in: query
         description: The pagination cursor value.
         schema:
-          type: string
+          type: string
+          minLength: 1
       - name: pageSize
         in: query
         description: Number of results to return per page.
         schema:
-          type: integer
+          type: integer
+          minimum: 1
+          maximum: 100
+          default: 10

426-505: Clarify/limit PATCH semantics for batch.calls

PatchedScheduledCallBatch allows modifying calls via writeOnly calls, but the endpoint description doesn’t define whether this replaces, appends, or forbids modification after creation. This can cause client confusion and server-side ambiguity.

Options:

  • Document precise semantics (“append-only”, “replace”, allowed statuses for mutation, idempotency) in the PATCH operation.
  • Or, remove calls from PatchedScheduledCallBatch and introduce explicit sub-resources for append/remove (e.g., POST /scheduled_batches/{batch_id}/scheduled_calls:append).

I can draft the OpenAPI oneOf/description updates if you confirm intended behavior.


506-542: Add an endpoint description for created_calls

Other list endpoints include a description; this one doesn’t. Add a brief description to aid SDK docs.

   '/api/agents/{agent_id}/scheduled_batches/{batch_id}/created_calls':
     get:
       tags:
         - agents
+      description: List calls that were created as a result of processing this batch.
       operationId: agents_scheduled_batches_created_calls_list

543-591: Consider multi-value filtering for status

Today status is a single string. It’s common to filter by multiple statuses (e.g., SUCCESS or ERROR). If that’s desired, model as an array with enum items and style=form, explode=true.

Example change:

-      - name: status
-        in: query
-        description: "* `FUTURE` - FUTURE\n* `PENDING` - PENDING\n* `SUCCESS` - SUCCESS\n* `EXPIRED` - EXPIRED\n* `ERROR` - ERROR"
-        schema:
-          minLength: 1
-          enum:
-            - FUTURE
-            - PENDING
-            - SUCCESS
-            - EXPIRED
-            - ERROR
-          type: string
+      - name: status
+        in: query
+        description: "Optional filter by one or more statuses."
+        style: form
+        explode: true
+        schema:
+          type: array
+          items:
+            type: string
+            enum: [FUTURE, PENDING, SUCCESS, EXPIRED, ERROR]

3301-3344: Minor: mark next/previous as readOnly for new paginated types

Some existing paginated schemas (e.g., PaginatedInvoiceList) mark next/previous as readOnly. Consider doing the same here for consistency.

     PaginatedScheduledCallBatchList:
       required:
         - results
       type: object
       properties:
         next:
           type: string
           format: uri
           nullable: true
+          readOnly: true
         previous:
           type: string
           format: uri
           nullable: true
+          readOnly: true
...
     PaginatedScheduledCallList:
       required:
         - results
       type: object
       properties:
         next:
           type: string
           format: uri
           nullable: true
+          readOnly: true
         previous:
           type: string
           format: uri
           nullable: true
+          readOnly: true

3575-3627: Double-check allowing calls in PATCH payload

Including calls (writeOnly) in PatchedScheduledCallBatch overlaps with creation and may complicate validation (e.g., partial updates vs. append). If mutation is allowed, please document constraints (size limits, deduplication keys, idempotency keys, allowed fields per ScheduledCallCreate).

If mutation is disallowed, remove calls from PatchedScheduledCallBatch to prevent accidental usage:

     PatchedScheduledCallBatch:
       type: object
       properties:
...
-        calls:
-          minItems: 1
-          type: array
-          items:
-            $ref: '#/components/schemas/ScheduledCall'
-          writeOnly: true

3758-3817: Optional: encode conditional requirement for webhookUrl

The description implies a conditional requirement (webhookUrl required if any call has a non-SIP medium). OpenAPI can’t easily express this across items, but we can:

  • Document this rule on ScheduledCallBatch.calls and ScheduledCallCreate.medium, or
  • Introduce a specialized oneOf with descriptive text.

At minimum, add an explicit note to ScheduledCallBatch.webhookUrl and ScheduledCallCreate.medium.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 2a0eefd and 659874b.

⛔ Files ignored due to path filters (43)
  • src/libs/Ultravox/Generated/Ultravox..JsonSerializerContext.g.cs is excluded by !**/generated/**
  • src/libs/Ultravox/Generated/Ultravox.AgentsClient.AgentsScheduledBatchesCreate.g.cs is excluded by !**/generated/**
  • src/libs/Ultravox/Generated/Ultravox.AgentsClient.AgentsScheduledBatchesCreatedCallsList.g.cs is excluded by !**/generated/**
  • src/libs/Ultravox/Generated/Ultravox.AgentsClient.AgentsScheduledBatchesDestroy.g.cs is excluded by !**/generated/**
  • src/libs/Ultravox/Generated/Ultravox.AgentsClient.AgentsScheduledBatchesList.g.cs is excluded by !**/generated/**
  • src/libs/Ultravox/Generated/Ultravox.AgentsClient.AgentsScheduledBatchesPartialUpdate.g.cs is excluded by !**/generated/**
  • src/libs/Ultravox/Generated/Ultravox.AgentsClient.AgentsScheduledBatchesRetrieve.g.cs is excluded by !**/generated/**
  • src/libs/Ultravox/Generated/Ultravox.AgentsClient.AgentsScheduledBatchesScheduledCallsList.g.cs is excluded by !**/generated/**
  • src/libs/Ultravox/Generated/Ultravox.IAgentsClient.AgentsScheduledBatchesCreate.g.cs is excluded by !**/generated/**
  • src/libs/Ultravox/Generated/Ultravox.IAgentsClient.AgentsScheduledBatchesCreatedCallsList.g.cs is excluded by !**/generated/**
  • src/libs/Ultravox/Generated/Ultravox.IAgentsClient.AgentsScheduledBatchesDestroy.g.cs is excluded by !**/generated/**
  • src/libs/Ultravox/Generated/Ultravox.IAgentsClient.AgentsScheduledBatchesList.g.cs is excluded by !**/generated/**
  • src/libs/Ultravox/Generated/Ultravox.IAgentsClient.AgentsScheduledBatchesPartialUpdate.g.cs is excluded by !**/generated/**
  • src/libs/Ultravox/Generated/Ultravox.IAgentsClient.AgentsScheduledBatchesRetrieve.g.cs is excluded by !**/generated/**
  • src/libs/Ultravox/Generated/Ultravox.IAgentsClient.AgentsScheduledBatchesScheduledCallsList.g.cs is excluded by !**/generated/**
  • src/libs/Ultravox/Generated/Ultravox.JsonConverters.AgentsScheduledBatchesScheduledCallsListStatus.g.cs is excluded by !**/generated/**
  • src/libs/Ultravox/Generated/Ultravox.JsonConverters.AgentsScheduledBatchesScheduledCallsListStatusNullable.g.cs is excluded by !**/generated/**
  • src/libs/Ultravox/Generated/Ultravox.JsonConverters.ScheduledCallStatusEnum.g.cs is excluded by !**/generated/**
  • src/libs/Ultravox/Generated/Ultravox.JsonConverters.ScheduledCallStatusEnumNullable.g.cs is excluded by !**/generated/**
  • src/libs/Ultravox/Generated/Ultravox.JsonConverters.WebhookStatusEnum.g.cs is excluded by !**/generated/**
  • src/libs/Ultravox/Generated/Ultravox.JsonConverters.WebhookStatusEnumNullable.g.cs is excluded by !**/generated/**
  • src/libs/Ultravox/Generated/Ultravox.JsonSerializerContextTypes.g.cs is excluded by !**/generated/**
  • src/libs/Ultravox/Generated/Ultravox.Models.AgentsScheduledBatchesScheduledCallsListStatus.g.cs is excluded by !**/generated/**
  • src/libs/Ultravox/Generated/Ultravox.Models.PaginatedScheduledCallBatchList.Json.g.cs is excluded by !**/generated/**
  • src/libs/Ultravox/Generated/Ultravox.Models.PaginatedScheduledCallBatchList.g.cs is excluded by !**/generated/**
  • src/libs/Ultravox/Generated/Ultravox.Models.PaginatedScheduledCallList.Json.g.cs is excluded by !**/generated/**
  • src/libs/Ultravox/Generated/Ultravox.Models.PaginatedScheduledCallList.g.cs is excluded by !**/generated/**
  • src/libs/Ultravox/Generated/Ultravox.Models.PatchedScheduledCallBatch.Json.g.cs is excluded by !**/generated/**
  • src/libs/Ultravox/Generated/Ultravox.Models.PatchedScheduledCallBatch.g.cs is excluded by !**/generated/**
  • src/libs/Ultravox/Generated/Ultravox.Models.PatchedWebhook.g.cs is excluded by !**/generated/**
  • src/libs/Ultravox/Generated/Ultravox.Models.ScheduledCall.Json.g.cs is excluded by !**/generated/**
  • src/libs/Ultravox/Generated/Ultravox.Models.ScheduledCall.g.cs is excluded by !**/generated/**
  • src/libs/Ultravox/Generated/Ultravox.Models.ScheduledCallBatch.Json.g.cs is excluded by !**/generated/**
  • src/libs/Ultravox/Generated/Ultravox.Models.ScheduledCallBatch.g.cs is excluded by !**/generated/**
  • src/libs/Ultravox/Generated/Ultravox.Models.ScheduledCallExperimentalSettings.Json.g.cs is excluded by !**/generated/**
  • src/libs/Ultravox/Generated/Ultravox.Models.ScheduledCallExperimentalSettings.g.cs is excluded by !**/generated/**
  • src/libs/Ultravox/Generated/Ultravox.Models.ScheduledCallMetadata.Json.g.cs is excluded by !**/generated/**
  • src/libs/Ultravox/Generated/Ultravox.Models.ScheduledCallMetadata.g.cs is excluded by !**/generated/**
  • src/libs/Ultravox/Generated/Ultravox.Models.ScheduledCallStatusEnum.g.cs is excluded by !**/generated/**
  • src/libs/Ultravox/Generated/Ultravox.Models.ScheduledCallTemplateContext.Json.g.cs is excluded by !**/generated/**
  • src/libs/Ultravox/Generated/Ultravox.Models.ScheduledCallTemplateContext.g.cs is excluded by !**/generated/**
  • src/libs/Ultravox/Generated/Ultravox.Models.Webhook.g.cs is excluded by !**/generated/**
  • src/libs/Ultravox/Generated/Ultravox.Models.WebhookStatusEnum.g.cs is excluded by !**/generated/**
📒 Files selected for processing (1)
  • src/libs/Ultravox/openapi.yaml (7 hunks)
🔇 Additional comments (1)
src/libs/Ultravox/openapi.yaml (1)

3991-3996: LGTM: WebhookStatusEnum

New enum is clear and scoped to webhooks. Descriptions map values to human-readable states. No issues.

Comment on lines 3706 to 3708
allOf:
- $ref: '#/components/schemas/StatusEnum'
- $ref: '#/components/schemas/WebhookStatusEnum'
readOnly: true
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Enum rename: StatusEnum → WebhookStatusEnum may be breaking for SDKs

You replaced the schema reference on Webhook.status/PatchedWebhook.status. Even though the field is readOnly, generated types change. Ensure:

  • All references to the removed StatusEnum are updated across the repo.
  • Release notes call out the enum rename for SDK consumers.

Run to verify no stragglers:

Also applies to: 3965-3967


🏁 Script executed:

#!/bin/bash
# Find lingering references to the old enum name.
rg -nP '\bStatusEnum\b' -C2

# Ensure Webhook.status is not used as writable anywhere.
rg -nP 'Webhook.*status' -C2 src | sed -n '1,120p'

Length of output: 1403


All code references updated—add release note for enum rename

  • Verified no lingering StatusEnum symbols in the repo (rg -nP '\bStatusEnum\b' -C2 returned nothing).
  • Confirmed both Webhook.status (line 3706–3708) and the analogous snippet at lines 3965–3967 now use WebhookStatusEnum and remain readOnly in the spec.
  • Action required: Update the release notes (or changelog) to clearly document the breaking change renaming StatusEnumWebhookStatusEnum for SDK consumers.
🤖 Prompt for AI Agents
In src/libs/Ultravox/openapi.yaml around lines 3706-3708 (and similarly
3965-3967), the OpenAPI schema renamed StatusEnum to WebhookStatusEnum which is
a breaking change for SDK consumers; update the project's release notes or
changelog to document this rename explicitly. Add an entry describing the change
(StatusEnum → WebhookStatusEnum), mark it as a breaking change, list affected
models/endpoints (e.g., Webhook.status), include migration guidance for SDK
users (how to update references/imports), and reference the spec lines or commit
where the rename occurred.

Comment on lines +3721 to +3757
required:
- batchId
- callId
- error
- status
type: object
properties:
status:
allOf:
- $ref: '#/components/schemas/ScheduledCallStatusEnum'
readOnly: true
batchId:
type: string
format: uuid
readOnly: true
callId:
type: string
format: uuid
nullable: true
readOnly: true
error:
type: string
nullable: true
readOnly: true
medium:
allOf:
- $ref: '#/components/schemas/ultravox.v1.CallMedium'
description: 'The call medium to use for the call. In particular, allows for specifying per-call recipients for outgoing SIP media.'
nullable: true
metadata:
nullable: true
templateContext:
description: The context used to render the agent's template.
nullable: true
experimentalSettings:
nullable: true
ScheduledCallBatch:
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix required+readOnly mix in ScheduledCall used for request payloads

ScheduledCall marks readOnly fields (status, batchId, callId, error) as required. Since ScheduledCallBatch.calls (both in create and patch) references ScheduledCall, code generators will force clients to provide these fields even though they’re readOnly, breaking ergonomics and in some languages preventing request compilation.

Introduce a request-only schema (ScheduledCallCreate) and reference it from ScheduledCallBatch.calls and PatchedScheduledCallBatch.calls. Keep ScheduledCall for responses.

Diff (add new schema and rewire refs):

@@
     PatchedScheduledCallBatch:
       type: object
       properties:
@@
-        calls:
-          minItems: 1
-          type: array
-          items:
-            $ref: '#/components/schemas/ScheduledCall'
-          writeOnly: true
+        calls:
+          minItems: 1
+          type: array
+          items:
+            $ref: '#/components/schemas/ScheduledCallCreate'
+          writeOnly: true
@@
     ScheduledCall:
       required:
         - batchId
         - callId
         - error
         - status
       type: object
       properties:
@@
         experimentalSettings:
           nullable: true
+
+    ScheduledCallCreate:
+      type: object
+      properties:
+        medium:
+          allOf:
+            - $ref: '#/components/schemas/ultravox.v1.CallMedium'
+          description: 'The call medium to use for the call. Allows per-call recipients for outgoing SIP.'
+          nullable: true
+        metadata:
+          nullable: true
+        templateContext:
+          description: The context used to render the agent's template.
+          nullable: true
+        experimentalSettings:
+          nullable: true
+      required: []
@@
     ScheduledCallBatch:
       required:
         - batchId
         - calls
         - completedCount
         - created
         - endedAt
         - totalCount
       type: object
       properties:
@@
-        calls:
-          minItems: 1
-          type: array
-          items:
-            $ref: '#/components/schemas/ScheduledCall'
-          writeOnly: true
+        calls:
+          minItems: 1
+          type: array
+          items:
+            $ref: '#/components/schemas/ScheduledCallCreate'
+          writeOnly: true

This keeps response shapes intact while making request shapes practical for clients.

Also applies to: 3818-3825

🤖 Prompt for AI Agents
In src/libs/Ultravox/openapi.yaml around lines 3721-3757 (and also apply same
fix for 3818-3825), ScheduledCall currently marks several properties as readOnly
but still lists them as required, which forces clients to send readOnly fields;
fix by adding a new request-only schema ScheduledCallCreate that mirrors
ScheduledCall but removes readOnly flags and omits required readOnly props
(status, batchId, callId, error), then update ScheduledCallBatch.calls (and
PatchedScheduledCallBatch.calls where used in create/patch request bodies) to
reference ScheduledCallCreate for incoming payloads while keeping the original
ScheduledCall schema for responses; ensure components/schemas includes the new
ScheduledCallCreate definition and all refs are updated accordingly.

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