Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/tender-falcons-direct.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@livekit/agents-plugin-anam": patch
---

feat(anam): add director notes config
10 changes: 9 additions & 1 deletion plugins/anam/etc/agents-plugin-anam.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,14 @@ export class AvatarSession extends voice.AvatarSession {
}

// @public (undocumented)
export function mintAvatarJoinToken(input: {
export type DirectorNotes = {
expressivity?: number;
presetStyle?: string;
customStylePrompt?: string;
};

// @public (undocumented)
export function mintAvatarJoinToken({ roomName, avatarIdentity, publishOnBehalf, apiKey, apiSecret, ttl, }: {
roomName: string;
avatarIdentity: string;
publishOnBehalf: string;
Expand All @@ -76,6 +83,7 @@ export type PersonaConfig = {
name?: string;
avatarId?: string;
avatarModel?: string;
directorNotes?: DirectorNotes;
personaId?: string;
};

Expand Down
6 changes: 6 additions & 0 deletions plugins/anam/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,11 @@ export class AnamAPI {
sessionOptions?: SessionOptions;
}) {
const pc = params.personaConfig;
const directorNotes = pc.directorNotes
? Object.fromEntries(
Object.entries(pc.directorNotes).filter(([, value]) => value !== undefined),
)
: undefined;
// Anam's personaConfig is a `oneOf`: reference a previously created
// (stateful) persona by `personaId` — the "dev flow" — or configure an
// ephemeral persona inline with name/avatarId/llmId. The two are mutually
Expand All @@ -145,6 +150,7 @@ export class AnamAPI {
// Only forward the avatar model version when set; otherwise let Anam
// fall back to the avatar's default model.
...(pc.avatarModel ? { avatarModel: pc.avatarModel } : {}),
...(directorNotes && Object.keys(directorNotes).length > 0 ? { directorNotes } : {}),
};
Comment on lines 150 to 154

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔍 directorNotes silently ignored when personaId is provided

When a user provides both personaId and directorNotes in their PersonaConfig, the directorNotes are silently dropped at plugins/anam/src/api.ts:143-144 because the personaId branch only sends { personaId: pc.personaId }. This is consistent with how avatarModel, name, and avatarId are also excluded in the personaId path, and the type comment at plugins/anam/src/types.ts:22 labels directorNotes as "(prod flow)" (i.e. ephemeral only). However, unlike the other fields which are clearly about defining a persona from scratch, directorNotes reads more like a per-session override that could plausibly apply to a pre-existing persona too. If the Anam API supports director notes as session-level overrides for stateful personas, this would need to be included in the personaId branch as well.

(Refers to lines 143-154)

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.


const payload: Record<string, unknown> = {
Expand Down
12 changes: 12 additions & 0 deletions plugins/anam/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
// SPDX-FileCopyrightText: 2025 LiveKit, Inc.
//
// SPDX-License-Identifier: Apache-2.0
/** @public */
export type DirectorNotes = {
/** Normalized expressivity in [0, 1] controlling how strongly the avatar responds to style/cues. */
expressivity?: number;
/** Built-in expressive style, mutually exclusive with customStylePrompt. */
presetStyle?: string;
/** Free-form expressive style prompt, mutually exclusive with presetStyle. */
customStylePrompt?: string;
};

/** @public */
export type PersonaConfig = {
/** Optional display name (prod flow) */
Expand All @@ -9,6 +19,8 @@ export type PersonaConfig = {
avatarId?: string;
/** Optional avatar model version, e.g. "cara-3" or "cara-4-latest" (prod flow) */
avatarModel?: string;
/** Optional per-session director-notes overrides (prod flow) */
directorNotes?: DirectorNotes;
/** Optional persona id (dev flow) */
personaId?: string;
};
Expand Down
Loading