Agent
Configure Astra, the workspace's AI phone agent: voice, greeting, jobs, business hours, routing — then publish it live.
Each workspace has one AI agent (shown as Astra in the app). It answers calls on the numbers routed to it and places outbound AI calls. Changes are saved as a draft and only reach live calls after you publish.
#The agent object
iduuidnamestring — What the agent calls itself on the phone.greetingstring | null — The first sentence on every answered call.tonestring | null — Free-text style guidance, for examplewarm and concise.voicestring | null —astra(default),luna,andromeda,celeste,albion,atrium,bondororion.languagestring | null — For exampleen-US.instructionsstring | null — Compiled instructions (read-only, built from the config and your knowledge).status"draft" | "published"enabledboolean — Master switch. Whenfalse, routed calls fall back to the team.timezonestring — IANA timezone used for business hours.businessHoursobject —{ mode: "always" }or{ mode: "scheduled", weekly: { mon: [{ start: "09:00", end: "17:00" }], … } }. Days aresun–sat; times are 24-hour andendis exclusive.inHoursAction/offHoursActionstring — Who answers during and outside business hours:agent,voicemail,app(ring the team) orforward.jobsarray of {name, instructions} — The tasks the agent handles (for example "Book appointments", "Answer pricing questions").
#Retrieve the agent
/v1/api/agentReturns the agent (null until one is created) and this cycle's AI credit usage.
Scope: agent:manage
Returns { agent, credits: { cycleId, used, included, remaining } | null }.
curl https://api.ody.co/v1/api/agent \
-H "Authorization: Bearer $ODY_API_KEY"const { agent, credits } = await ody.agent.get();res = client.agent.get(){
"agent": {
"id": "0d9c…",
"name": "Astra",
"greeting": "Thanks for calling Acme Plumbing, this is Astra. How can I help?",
"voice": "astra",
"status": "published",
"enabled": true,
"timezone": "America/Chicago",
"businessHours": { "mode": "scheduled", "weekly": { "mon": [{ "start": "08:00", "end": "18:00" }] } },
"inHoursAction": "agent",
"offHoursAction": "agent",
"jobs": [{ "name": "Book appointments", "instructions": "Offer the next two open slots." }]
},
"credits": { "cycleId": "2026-10", "used": 1200, "included": 3000, "remaining": 1800 }
}#Update the agent
/v1/api/agentCreates the agent if there isn't one yet, otherwise updates the draft. Only the fields you send change. jobs is replaced wholesale. Send at least one field.
Changes don't reach live calls until you publish.
Scope: agent:manage
Body: any of name, greeting, tone, voice, language, timezone, businessHours, inHoursAction, offHoursAction, enabled, jobs. See the agent object above.
Returns { agent }.
curl -X PATCH https://api.ody.co/v1/api/agent \
-H "Authorization: Bearer $ODY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"greeting": "Thanks for calling Acme Plumbing, this is Astra. How can I help?",
"voice": "luna",
"timezone": "America/Chicago",
"offHoursAction": "agent",
"jobs": [
{ "name": "Book appointments", "instructions": "Offer the next two open slots." },
{ "name": "Emergencies", "instructions": "For burst pipes, take the address and say a plumber will call back within 15 minutes." }
]
}'await ody.agent.update({
greeting: "Thanks for calling Acme Plumbing, this is Astra. How can I help?",
voice: "luna",
timezone: "America/Chicago",
offHoursAction: "agent",
jobs: [{ name: "Book appointments", instructions: "Offer the next two open slots." }],
});client.agent.update(
greeting="Thanks for calling Acme Plumbing, this is Astra. How can I help?",
voice="luna",
timezone="America/Chicago",
off_hours_action="agent",
jobs=[{"name": "Book appointments", "instructions": "Offer the next two open slots."}],
)#Publish the agent
/v1/api/agent/publishPushes the saved configuration live to the telephony layer. New calls use it within seconds. With a test key, publishing is simulated.
Scope: agent:manage
Returns { agent, simulated? }. Returns 409 when the configuration is incomplete; the message says what's missing.
curl -X POST https://api.ody.co/v1/api/agent/publish \
-H "Authorization: Bearer $ODY_API_KEY"await ody.agent.publish();client.agent.publish()What the agent knows (your services, prices, FAQs) comes from the workspace's knowledge sources: website pages and notes added under Astra → Knowledge in the app. Those aren't editable through the API yet.