Subjects
People, products, and brands being promoted.
13 actions. Each is callable by the agent as a tool, over HTTP via /api/invoke, and (usually) from a UI page.
subjects.list
GET
List subjects (people, products, brands, etc.) being promoted.
- AI tool:
subjects_list - API:
GET /api/invoke/subjects.list
Input
| Field | Type | Required | Description |
|---|---|---|---|
limit |
integer | — | |
offset |
integer | — | |
orderBy |
string | — | |
orderDir |
"asc" | "desc" | — | |
q |
string | — |
JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"limit": {
"type": "integer",
"minimum": 1,
"maximum": 500
},
"offset": {
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991
},
"orderBy": {
"type": "string"
},
"orderDir": {
"type": "string",
"enum": [
"asc",
"desc"
]
},
"q": {
"type": "string"
}
}
}subjects.search
GET
Find subjects matching a query (name, handle, tags, or URL).
- AI tool:
subjects_search - API:
GET /api/invoke/subjects.search
Input
| Field | Type | Required | Description |
|---|---|---|---|
q |
string | yes |
JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"q": {
"type": "string"
}
},
"required": [
"q"
]
}subjects.get
GET
Get one subject by id.
- AI tool:
subjects_get - API:
GET /api/invoke/subjects.get
Input
| Field | Type | Required | Description |
|---|---|---|---|
id |
string | yes |
JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"id": {
"type": "string",
"minLength": 1
}
},
"required": [
"id"
]
}subjects.create
POST · mutating
Create a new subject (person/product/brand) to promote. Returns the new subject.
When the agent calls it: Call this when the user wants to promote a person, product, brand, project, event, or company that does not yet exist in the platform. type MUST be exactly one of: person, product, brand, project, event, company. Pick the closest fit (a place/home/property → project; an organization → company) — never pass a value outside this list. Only name and type are required. Use the returned subject id for follow-up calls like missions.create.
- AI tool:
subjects_create - API:
POST /api/invoke/subjects.create
Input
| Field | Type | Required | Description |
|---|---|---|---|
type |
"person" | "product" | "brand" | "project" | "event" | "company" | yes | |
name |
string | yes | |
handle |
string | — | |
headline |
string | — | |
description |
string | — | |
bio |
string | — | |
tags |
string[] | — | |
expertise |
string[] | — | |
links |
object[] | — |
JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"person",
"product",
"brand",
"project",
"event",
"company"
]
},
"name": {
"type": "string"
},
"handle": {
"type": "string"
},
"headline": {
"type": "string"
},
"description": {
"default": "",
"type": "string"
},
"bio": {
"type": "string"
},
"tags": {
"default": [],
"type": "array",
"items": {
"type": "string"
}
},
"expertise": {
"default": [],
"type": "array",
"items": {
"type": "string"
}
},
"links": {
"default": [],
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"type": {
"type": "string",
"enum": [
"github",
"website",
"twitter",
"linkedin",
"youtube",
"instagram",
"tiktok",
"threads",
"bluesky",
"blog",
"paper",
"talk",
"podcast",
"document",
"pdf",
"other"
]
},
"url": {
"type": "string",
"format": "uri"
},
"label": {
"type": "string"
},
"verified": {
"type": "boolean"
},
"followers": {
"type": "number"
}
},
"required": [
"type",
"url"
]
}
}
},
"required": [
"type",
"name"
]
}subjects.update
PATCH · mutating
Update fields on a subject.
When the agent calls it: To add facts, pass patch.facts as an array of { fact: "
", source?: " " }. Do not include ids or confidence — the server fills those in.
- AI tool:
subjects_update - API:
PATCH /api/invoke/subjects.update
Input
| Field | Type | Required | Description |
|---|---|---|---|
id |
string | yes | |
patch |
object | yes |
JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"id": {
"type": "string",
"minLength": 1
},
"patch": {
"type": "object",
"properties": {
"id": {
"type": "string",
"minLength": 1
},
"type": {
"type": "string",
"enum": [
"person",
"product",
"brand",
"project",
"event",
"company"
]
},
"name": {
"type": "string"
},
"handle": {
"type": "string"
},
"headline": {
"type": "string"
},
"description": {
"type": "string"
},
"bio": {
"type": "string"
},
"tags": {
"default": [],
"type": "array",
"items": {
"type": "string"
}
},
"expertise": {
"default": [],
"type": "array",
"items": {
"type": "string"
}
},
"links": {
"default": [],
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"type": {
"type": "string",
"enum": [
"github",
"website",
"twitter",
"linkedin",
"youtube",
"instagram",
"tiktok",
"threads",
"bluesky",
"blog",
"paper",
"talk",
"podcast",
"document",
"pdf",
"other"
]
},
"url": {
"type": "string",
"format": "uri"
},
"label": {
"type": "string"
},
"verified": {
"type": "boolean"
},
"followers": {
"type": "number"
}
},
"required": [
"type",
"url"
]
}
},
"voice": {
"type": "object",
"properties": {
"tone": {
"default": [],
"type": "array",
"items": {
"type": "string"
}
},
"doList": {
"default": [],
"type": "array",
"items": {
"type": "string"
}
},
"dontList": {
"default": [],
"type": "array",
"items": {
"type": "string"
}
},
"examplePosts": {
"default": [],
"type": "array",
"items": {
"type": "string"
}
},
"forbiddenTopics": {
"default": [],
"type": "array",
"items": {
"type": "string"
}
},
"catchphrases": {
"default": [],
"type": "array",
"items": {
"type": "string"
}
}
}
},
"audienceProfile": {
"type": "object",
"properties": {
"primaryAudience": {
"type": "string"
},
"demographics": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"anyOf": [
{
"type": "string"
},
{
"type": "number"
}
]
}
},
"interests": {
"default": [],
"type": "array",
"items": {
"type": "string"
}
}
}
},
"facts": {
"type": "array",
"items": {
"type": "object",
"properties": {
"fact": {
"type": "string"
},
"source": {
"type": "string"
},
"confidence": {
"type": "number",
"minimum": 0,
"maximum": 1
},
"category": {
"type": "string"
}
},
"required": [
"fact"
]
}
},
"createdAt": {},
"updatedAt": {}
}
}
},
"required": [
"id",
"patch"
]
}subjects.delete
DELETE · mutating
Soft-delete a subject. Sets deleted_at on the subject and cascade soft-deletes every mission tied to it. Reversible via subjects.restore. The row stays in the database so historical references (drafts, decisions, engagements) keep resolving.
When the agent calls it: Use this when the user wants to remove a subject from active lists. Confirms with the user first — cascades to all of the subject's missions.
- AI tool:
subjects_delete - API:
DELETE /api/invoke/subjects.delete
Input
| Field | Type | Required | Description |
|---|---|---|---|
id |
string | yes |
JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"id": {
"type": "string",
"minLength": 1
}
},
"required": [
"id"
]
}subjects.restore
POST · mutating
Restore a soft-deleted subject by clearing its deleted_at. Does NOT auto-restore cascaded missions — caller must restore those individually if desired.
- AI tool:
subjects_restore - API:
POST /api/invoke/subjects.restore
Input
| Field | Type | Required | Description |
|---|---|---|---|
id |
string | yes |
JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"id": {
"type": "string",
"minLength": 1
}
},
"required": [
"id"
]
}subjects.derive_voice
POST · mutating
Run the voice-profile derivation pass on a subject. When platform is set, derives a per-platform voice (different audience → different tone) under voice.byPlatform[platform]. When omitted, derives or returns the default profile. Per-platform presets cover twitter / patreon / devto / kickstarter / reddit / hackernews / producthunt / linkedin / instagram.
When the agent calls it: For a subject that posts on multiple platforms, derive voices ONE PLATFORM AT A TIME — call with platform="patreon", then "twitter", then "devto" etc. Each call adds to voice.byPlatform without disturbing the others.
- AI tool:
subjects_derive_voice - API:
POST /api/invoke/subjects.derive_voice
Input
| Field | Type | Required | Description |
|---|---|---|---|
id |
string | yes | |
platform |
string | — |
JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"id": {
"type": "string",
"minLength": 1
},
"platform": {
"type": "string"
}
},
"required": [
"id"
]
}subjects.upsert_recipe
POST · mutating
Add or replace a publishing recipe on a subject. Recipes describe the default cadence for a category of content (dev-log, game-update, milestone, etc.) — each lists the channels to post on, in order, with delays. publish_to_channels reads these.
When the agent calls it: Recipe names are how the agent matches a topic to a cadence. Good names: "dev-log", "game-update", "milestone-celebration", "behind-the-scenes". Include
matchKeywordsto bias the classifier.
- AI tool:
subjects_upsert_recipe - API:
POST /api/invoke/subjects.upsert_recipe
Input
| Field | Type | Required | Description |
|---|---|---|---|
id |
string | yes | |
recipe |
object | yes |
JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"id": {
"type": "string",
"minLength": 1
},
"recipe": {
"type": "object",
"properties": {
"name": {
"type": "string",
"minLength": 1
},
"description": {
"type": "string"
},
"matchKeywords": {
"type": "array",
"items": {
"type": "string"
}
},
"channels": {
"minItems": 1,
"type": "array",
"items": {
"type": "object",
"properties": {
"order": {
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991
},
"platform": {
"type": "string"
},
"personaSubjectId": {
"type": "string",
"minLength": 1
},
"contentMode": {
"type": "string"
},
"delayMinutes": {
"default": 0,
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991
},
"hashtags": {
"type": "array",
"items": {
"type": "string"
}
},
"audienceHint": {
"type": "string"
}
},
"required": [
"order",
"platform"
]
}
}
},
"required": [
"name",
"channels"
]
}
},
"required": [
"id",
"recipe"
]
}subjects.delete_recipe
DELETE · mutating
Remove a publishing recipe by name from a subject.
- AI tool:
subjects_delete_recipe - API:
DELETE /api/invoke/subjects.delete_recipe
Input
| Field | Type | Required | Description |
|---|---|---|---|
id |
string | yes | |
name |
string | yes |
JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"id": {
"type": "string",
"minLength": 1
},
"name": {
"type": "string"
}
},
"required": [
"id",
"name"
]
}subjects.list_recipes
GET
List publishing recipes attached to a subject.
- AI tool:
subjects_list_recipes - API:
GET /api/invoke/subjects.list_recipes
Input
| Field | Type | Required | Description |
|---|---|---|---|
id |
string | yes |
JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"id": {
"type": "string",
"minLength": 1
}
},
"required": [
"id"
]
}subjects.resolve_recipe
POST
Pick one publishing recipe for a topic. When recipeName is provided, looks it up directly; otherwise runs the keyword classifier over the subject's recipes. Returns the recipe + classifier reason + confidence. Used by the platform-fanout workflow's first node to populate runningContext.recipe — then the foreach node iterates over recipe.channels.
- AI tool:
subjects_resolve_recipe - API:
POST /api/invoke/subjects.resolve_recipe
Input
| Field | Type | Required | Description |
|---|---|---|---|
subjectId |
string | yes | |
topic |
string | yes | |
recipeName |
string | — | |
useLlm |
boolean | — |
JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"subjectId": {
"type": "string",
"minLength": 1
},
"topic": {
"type": "string"
},
"recipeName": {
"type": "string"
},
"useLlm": {
"type": "boolean"
}
},
"required": [
"subjectId",
"topic"
]
}subjects.find_similar
GET
Find subjects most semantically similar to a free-text query (pgvector kNN).
- AI tool:
subjects_find_similar - API:
GET /api/invoke/subjects.find_similar
Input
| Field | Type | Required | Description |
|---|---|---|---|
text |
string | yes | |
limit |
integer | — |
JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"text": {
"type": "string"
},
"limit": {
"default": 10,
"type": "integer",
"minimum": 1,
"maximum": 50
}
},
"required": [
"text"
]
}