Agent Core
The Agent Core API exposes the agent setup canvas (gen.pro/{agent_id}/setup) as a flat, PAT-authenticated API. One GET returns every field; one PATCH updates any subset. Field names mirror exactly what the Setup canvas FE saves, so developers and the FE speak the same language.
Use this when you want to configure an agent programmatically. It replaces having to call multiple endpoints separately.
Fields
Section titled “Fields”A single PATCH may update multiple internal systems at once. You see one call and get 200 if all succeed, or 207 Multi-Status with per-section status if any one section fails.
Important distinctions
Section titled “Important distinctions”linked_accounts vs monitored vs research_topics — these are three different concepts.
linked_accounts= the agent’s own brand social accounts (the TikTok/Instagram/website the agent posts from).monitored= inspiration sources — other creators, hashtags, or search keywords the agent watches for trending content.research_topics= expertise areas (labeled “Expertise” in the UI) — subjects the agent needs to stay current on. The platform automatically researches each topic daily and feeds the results into content generation. Only include topics where recent events matter — leave empty for evergreen niches.
Don’t mix them. Putting a competitor’s TikTok URL in linked_accounts will eventually appear on the agent’s own “My Socials” list and confuse the content pipeline.
description vs personality — these are different lengths.
descriptionis a 2-3 sentence brand summary. Hard-capped at 500 characters.personalityis the full persona text — voice, backstory, behavior rules. Max 20000 characters.
If you try to put a 3000-character persona into description, the API returns a 422. This is intentional.
Get the full agent setup
Section titled “Get the full agent setup”GET /v1/agents/{agent_id}/coreReturns every field as a flat object. Fields that haven’t been set return null or empty arrays.
Response 200:
{ "agent_id": "abc123", "brand_name": "Santiago", "description": "Santiago is a San Antonio street food scout who hunts the best tacos in the city.", "identity_type": "character", "goal": "growth", "target_platforms": ["tiktok", "instagram"], "shortform": true, "longform": false, "onboarding_status": "profile_complete", "keywords": ["streetfood", "tacotok", "sanantonioeats", "foodtruckfinds"], "monitored": [ { "handle": "https://tiktok.com/@keilapacheco", "item_type": "account" }, { "handle": "tacotok", "item_type": "hashtag" } ], "research_topics": [ { "topic": "new food truck openings in San Antonio" }, { "topic": "viral street food TikTok moments" }, { "topic": "Texas food festival announcements" } ], "linked_accounts": [ { "id": 42, "url": "https://tiktok.com/@santiago_real", "platform": "tiktok", "display_name": "Santiago 🌮" } ], "personality": "Santiago grew up eating at his tía's taco stand in south San Antonio...", "default_user_voice": { "voice_id": "21m00Tcm4TlvDq8ikWAM", "name": "Rachel", "source": "public" }}Update the agent setup
Section titled “Update the agent setup”PATCH /v1/agents/{agent_id}/coreFlat merge-patch body. Send only the fields you want to change — omitted fields are left unchanged.
Field-level semantics
Section titled “Field-level semantics”| Field | Semantics |
|---|---|
Scalars (brand_name, description, identity_type, goal, shortform, longform, onboarding_status, personality) | Replace |
keywords | Replace the full list |
target_platforms | Replace the full list |
monitored | Replace the full list — items you don’t send are deleted |
research_topics | Replace the full list — topics you don’t send are deleted. Max 20 items. |
linked_accounts | Replace the full list — rows you don’t send are deleted. Rows with id are updated in place; rows without id are inserted. |
default_user_voice | Replace |
To add a single monitored item or linked_account without touching others, GET /core first, append, then PATCH with the full list.
Validation guardrails
Section titled “Validation guardrails”- Unknown fields return 422 (
extra="forbid"on every model). descriptionmax 500 chars.personalitymax 20000 chars.identity_typestrict enum:"brand"|"character".monitored[].item_typestrict enum:"account"|"hashtag"|"keyword".research_topicsmax 20 items, eachtopicmax 500 chars.linked_accounts[].urlrequired.monitored[],research_topics[], andlinked_accounts[]also reject unknown keys.
Keyword → monitored auto-mirror
Section titled “Keyword → monitored auto-mirror”If you send keywords without also sending monitored, the writer automatically populates monitored with [{handle: kw, item_type: "keyword"}] for each keyword, so the nightly monitoring cron stays in sync. This matches what the brand-analysis onboarding task does. If you send both, your explicit monitored wins — the auto-mirror is skipped.
Response
Section titled “Response”200 on full success, 207 Multi-Status on partial failure. The body is a map keyed by upstream target, not by request field:
{ "brand": { "status": "ok", "data": { "brand_name": "Santiago", "keywords": ["streetfood"], ... } }, "personality": { "status": "ok", "data": "Santiago grew up eating at..." }, "voice": { "status": "error", "error": "voice service unavailable" }}Sections only appear if the PATCH touched at least one field they own. A PATCH that only sets brand_name returns { "brand": { "status": "ok", ... } } — no personality or voice entry.
Example — set up a character in one call
Section titled “Example — set up a character in one call”curl -X PATCH https://api.gen.pro/v1/agents/abc123/core \ -H "X-API-Key: $GEN_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "brand_name": "Santiago", "description": "Santiago is a San Antonio street food scout who hunts the best tacos in the city.", "identity_type": "character", "goal": "growth", "target_platforms": ["tiktok", "instagram"], "shortform": true, "longform": false, "onboarding_status": "profile_complete", "keywords": ["streetfood", "tacotok", "sanantonioeats"], "monitored": [ { "handle": "https://tiktok.com/@keilapacheco", "item_type": "account" }, { "handle": "tacotok", "item_type": "hashtag" } ], "research_topics": [ { "topic": "new food truck openings in San Antonio" }, { "topic": "viral street food TikTok moments" } ], "linked_accounts": [ { "url": "https://tiktok.com/@santiago_real", "platform": "tiktok", "display_name": "Santiago" } ], "personality": "Santiago grew up eating at his tía'\''s taco stand in south San Antonio. He'\''s 28, easy-going, trusts his tongue over reviews, and will fight anyone who says Austin has better tacos.", "default_user_voice": { "voice_id": "21m00Tcm4TlvDq8ikWAM", "source": "public" } }'TypeScript SDK equivalent:
import { GenClient } from '@poweredbygen/gen-sdk';
const gen = new GenClient({ apiKey: process.env.GEN_API_KEY! });
const result = await gen.agents.updateCore('abc123', { brand_name: 'Santiago', description: 'San Antonio street food scout who hunts the best tacos.', identity_type: 'character', goal: 'growth', target_platforms: ['tiktok', 'instagram'], shortform: true, keywords: ['streetfood', 'tacotok', 'sanantonioeats'], monitored: [ { handle: 'https://tiktok.com/@keilapacheco', item_type: 'account' }, ], research_topics: [ { topic: 'new food truck openings in San Antonio' }, { topic: 'viral street food TikTok moments' }, ], linked_accounts: [ { url: 'https://tiktok.com/@santiago_real', platform: 'tiktok' }, ], personality: 'Santiago grew up eating at his tía\'s taco stand...', default_user_voice: { voice_id: '21m00Tcm4TlvDq8ikWAM', source: 'public' },});
if (result.personality?.status === 'error') { console.error('personality write failed:', result.personality.error);}Errors
Section titled “Errors”| Code | Meaning |
|---|---|
| 401 | Missing or invalid X-API-Key |
| 404 | Agent not found |
| 422 | Validation error — unknown field, bad enum, length cap exceeded, or missing required sub-field like monitored[].item_type |
| 207 | Partial success. Inspect per-target status in the response body. |
Related
Section titled “Related”- Voice API — voice library, design, cloning, preview (separate endpoint tree)
- Discovery API — listing agents, workspaces, organizations