-
-
Notifications
You must be signed in to change notification settings - Fork 0
feat:Add agent-scoped scheduled batch APIs and update webhook status enum #122
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
WalkthroughIntroduces 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
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
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)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Poem
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
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this 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 endpointsFor 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.callsPatchedScheduledCallBatch 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_callsOther 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 statusToday 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 typesSome 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 payloadIncluding 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 webhookUrlThe 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.
⛔ Files ignored due to path filters (43)
src/libs/Ultravox/Generated/Ultravox..JsonSerializerContext.g.csis excluded by!**/generated/**src/libs/Ultravox/Generated/Ultravox.AgentsClient.AgentsScheduledBatchesCreate.g.csis excluded by!**/generated/**src/libs/Ultravox/Generated/Ultravox.AgentsClient.AgentsScheduledBatchesCreatedCallsList.g.csis excluded by!**/generated/**src/libs/Ultravox/Generated/Ultravox.AgentsClient.AgentsScheduledBatchesDestroy.g.csis excluded by!**/generated/**src/libs/Ultravox/Generated/Ultravox.AgentsClient.AgentsScheduledBatchesList.g.csis excluded by!**/generated/**src/libs/Ultravox/Generated/Ultravox.AgentsClient.AgentsScheduledBatchesPartialUpdate.g.csis excluded by!**/generated/**src/libs/Ultravox/Generated/Ultravox.AgentsClient.AgentsScheduledBatchesRetrieve.g.csis excluded by!**/generated/**src/libs/Ultravox/Generated/Ultravox.AgentsClient.AgentsScheduledBatchesScheduledCallsList.g.csis excluded by!**/generated/**src/libs/Ultravox/Generated/Ultravox.IAgentsClient.AgentsScheduledBatchesCreate.g.csis excluded by!**/generated/**src/libs/Ultravox/Generated/Ultravox.IAgentsClient.AgentsScheduledBatchesCreatedCallsList.g.csis excluded by!**/generated/**src/libs/Ultravox/Generated/Ultravox.IAgentsClient.AgentsScheduledBatchesDestroy.g.csis excluded by!**/generated/**src/libs/Ultravox/Generated/Ultravox.IAgentsClient.AgentsScheduledBatchesList.g.csis excluded by!**/generated/**src/libs/Ultravox/Generated/Ultravox.IAgentsClient.AgentsScheduledBatchesPartialUpdate.g.csis excluded by!**/generated/**src/libs/Ultravox/Generated/Ultravox.IAgentsClient.AgentsScheduledBatchesRetrieve.g.csis excluded by!**/generated/**src/libs/Ultravox/Generated/Ultravox.IAgentsClient.AgentsScheduledBatchesScheduledCallsList.g.csis excluded by!**/generated/**src/libs/Ultravox/Generated/Ultravox.JsonConverters.AgentsScheduledBatchesScheduledCallsListStatus.g.csis excluded by!**/generated/**src/libs/Ultravox/Generated/Ultravox.JsonConverters.AgentsScheduledBatchesScheduledCallsListStatusNullable.g.csis excluded by!**/generated/**src/libs/Ultravox/Generated/Ultravox.JsonConverters.ScheduledCallStatusEnum.g.csis excluded by!**/generated/**src/libs/Ultravox/Generated/Ultravox.JsonConverters.ScheduledCallStatusEnumNullable.g.csis excluded by!**/generated/**src/libs/Ultravox/Generated/Ultravox.JsonConverters.WebhookStatusEnum.g.csis excluded by!**/generated/**src/libs/Ultravox/Generated/Ultravox.JsonConverters.WebhookStatusEnumNullable.g.csis excluded by!**/generated/**src/libs/Ultravox/Generated/Ultravox.JsonSerializerContextTypes.g.csis excluded by!**/generated/**src/libs/Ultravox/Generated/Ultravox.Models.AgentsScheduledBatchesScheduledCallsListStatus.g.csis excluded by!**/generated/**src/libs/Ultravox/Generated/Ultravox.Models.PaginatedScheduledCallBatchList.Json.g.csis excluded by!**/generated/**src/libs/Ultravox/Generated/Ultravox.Models.PaginatedScheduledCallBatchList.g.csis excluded by!**/generated/**src/libs/Ultravox/Generated/Ultravox.Models.PaginatedScheduledCallList.Json.g.csis excluded by!**/generated/**src/libs/Ultravox/Generated/Ultravox.Models.PaginatedScheduledCallList.g.csis excluded by!**/generated/**src/libs/Ultravox/Generated/Ultravox.Models.PatchedScheduledCallBatch.Json.g.csis excluded by!**/generated/**src/libs/Ultravox/Generated/Ultravox.Models.PatchedScheduledCallBatch.g.csis excluded by!**/generated/**src/libs/Ultravox/Generated/Ultravox.Models.PatchedWebhook.g.csis excluded by!**/generated/**src/libs/Ultravox/Generated/Ultravox.Models.ScheduledCall.Json.g.csis excluded by!**/generated/**src/libs/Ultravox/Generated/Ultravox.Models.ScheduledCall.g.csis excluded by!**/generated/**src/libs/Ultravox/Generated/Ultravox.Models.ScheduledCallBatch.Json.g.csis excluded by!**/generated/**src/libs/Ultravox/Generated/Ultravox.Models.ScheduledCallBatch.g.csis excluded by!**/generated/**src/libs/Ultravox/Generated/Ultravox.Models.ScheduledCallExperimentalSettings.Json.g.csis excluded by!**/generated/**src/libs/Ultravox/Generated/Ultravox.Models.ScheduledCallExperimentalSettings.g.csis excluded by!**/generated/**src/libs/Ultravox/Generated/Ultravox.Models.ScheduledCallMetadata.Json.g.csis excluded by!**/generated/**src/libs/Ultravox/Generated/Ultravox.Models.ScheduledCallMetadata.g.csis excluded by!**/generated/**src/libs/Ultravox/Generated/Ultravox.Models.ScheduledCallStatusEnum.g.csis excluded by!**/generated/**src/libs/Ultravox/Generated/Ultravox.Models.ScheduledCallTemplateContext.Json.g.csis excluded by!**/generated/**src/libs/Ultravox/Generated/Ultravox.Models.ScheduledCallTemplateContext.g.csis excluded by!**/generated/**src/libs/Ultravox/Generated/Ultravox.Models.Webhook.g.csis excluded by!**/generated/**src/libs/Ultravox/Generated/Ultravox.Models.WebhookStatusEnum.g.csis 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: WebhookStatusEnumNew enum is clear and scoped to webhooks. Descriptions map values to human-readable states. No issues.
| allOf: | ||
| - $ref: '#/components/schemas/StatusEnum' | ||
| - $ref: '#/components/schemas/WebhookStatusEnum' | ||
| readOnly: true |
There was a problem hiding this comment.
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
StatusEnumsymbols in the repo (rg -nP '\bStatusEnum\b' -C2returned nothing). - Confirmed both
Webhook.status(line 3706–3708) and the analogous snippet at lines 3965–3967 now useWebhookStatusEnumand remainreadOnlyin the spec. - Action required: Update the release notes (or changelog) to clearly document the breaking change renaming
StatusEnum→WebhookStatusEnumfor 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.
| 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: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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: trueThis 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.
Summary by CodeRabbit
New Features
Refactor
Chores