Header Logo

How to Lock Down Avatar Outfit, Face, and Voice Customization in a Multitenant AI Avatar Platform

How to Lock Down Avatar Outfit, Face, and Voice Customization in a Multitenant AI Avatar Platform

Multitenant AI avatar policy for outfit, face, and voice: server-side whitelists, session validation, and tenant isolation.

Introduction


In a multitenant avatar platform, “customization” is really three separate control planes: outfit, face, and voice. If you let customers define all three, you also inherit the usual SaaS problems: tenant isolation, policy enforcement, versioning, abuse prevention, and predictable billing. The hard part is not rendering an avatar; it’s making sure one tenant cannot drift outside the assets, voices, or branding rules they are allowed to use.


By the end of this post, you should be able to design a customization model that is easy to reason about, enforce it consistently across realtime sessions, and avoid the common mistakes that cause brand leakage or “why did this tenant get the wrong voice?” incidents. I’ll also show where Protoface fits when you want to expose these controls through a realtime avatar API rather than building the media stack yourself.


Start with a tenant policy, not with UI toggles


The first mistake is to treat customization as a front-end problem. If the browser or the client app decides which outfit, face, or voice to use, you’ve already lost the enforcement boundary. The server should own a tenant policy object that defines the allowed set of avatar assets and the rules for selecting them.


At minimum, model three kinds of constraints:


  • Allowed asset sets: explicit lists of approved face IDs, outfit IDs, and voice IDs.

  • Default selections: what gets used when the client omits a choice.

  • Override rules: whether end users can pick from a subset, or only admins can change a tenant’s defaults.


A practical policy shape looks like this:


{
}
{
}
{
}


This policy should be stored and enforced server-side. The client can request a configuration, but the backend resolves it to a permitted value. That prevents “creative” clients from passing arbitrary asset identifiers into your session creation flow.


Separate identity from presentation


Outfit, face, and voice are related but should not be treated as one blob. A single avatar identity may have multiple presentations. For example, a support tenant might use the same face across all regions but vary the voice by locale, or keep voice fixed but swap outfits for different product lines. Keeping these dimensions separate gives you cleaner policy and better auditability.


In practice, model an avatar as:


  • Identity: the stable avatar record.

  • Presentation: the chosen face, outfit, and voice for a specific session.

  • Tenant policy: the allowed combinations for that tenant.


This matters because some combinations should never exist. A branded corporate face may only be valid with a small set of outfits, while a voice may be restricted by language, age rating, or region. If you let the frontend combine arbitrary choices, you’ll eventually create invalid or noncompliant combinations that only show up in production.


Validate combinations at session creation time


Enforcement is most reliable at the point where a realtime session is minted. That is the moment when the system knows the tenant, the requested presentation, and the downstream runtime that will render the avatar.


For a voice agent with a synchronized video face, the flow should be:


  1. Authenticate the caller as a specific tenant.

  2. Load the tenant policy.

  3. Resolve the requested face, outfit, and voice against the allowed sets.

  4. Reject invalid combinations with a deterministic error.

  5. Create the session only with normalized, server-approved values.


Do not allow downstream components to “fix up” invalid requests. If session creation accepts a request for an unapproved voice, your media layer becomes the policy engine, which is the wrong place to discover a violation. Fail fast and fail before any realtime resources are allocated.


A simple API call might look like this:


curl -X POST https://api.protoface.com/v1/sessions \
}'
curl -X POST https://api.protoface.com/v1/sessions \
}'
curl -X POST https://api.protoface.com/v1/sessions \
}'


The exact fields depend on the API, but the design principle is the important part: client intent goes in, server-approved session parameters come out.


Use a whitelist, not free-form customization


For multitenant systems, free-form avatar editing is usually a trap. If tenants can upload arbitrary face meshes, outfits, or voices, you introduce moderation, abuse, and quality problems that are orthogonal to your core product. Most teams are better off with a whitelist model:


  • Faces are selected from a curated library.

  • Outfits are preset templates with approved branding.

  • Voices are chosen from an approved catalog or per-tenant assignment.


That gives you strong control over visual identity and audio consistency. It also simplifies billing, because quality tier can be tied to a known set of assets and rendering paths rather than arbitrary user content.


If you do need limited tenant-level customization, make it metadata-driven. For example, let tenants choose a color palette or badge overlay, but keep the underlying face model fixed. The more you let customers swap core media assets, the more you need explicit review, storage governance, and rollback support.


Keep voice selection tied to the agent, not the browser


Voice is especially sensitive because it affects both brand consistency and user trust. In a realtime avatar system, the voice is usually owned by the agent runtime: the TTS engine or voice provider generates audio, and the avatar renders lip sync against that stream. If the browser can pick the voice directly, you’ve effectively delegated identity control to an untrusted client.


Instead, bind voice selection to the session or agent configuration on the server. That lets you enforce policies like:


  • only approved voices for a tenant,

  • language-specific voice mappings,

  • per-environment differences between staging and production,

  • regional restrictions based on legal or contractual requirements.


This also keeps the audio and video synchronized. If the agent runtime knows the exact voice at session start, the video face can be initialized with matching timing and expression parameters. That reduces visible mismatch during the first few seconds of a call, which is where these systems most often look broken.


Enforce embed and API boundaries separately


If you expose an iframe embed, the browser still shouldn’t be able to choose arbitrary assets. The iframe boundary is great for keeping credentials out of the client and reducing integration complexity, but it does not replace server-side policy. The same tenant rules should apply whether the session is created through your REST API, your Python SDK, or an embedded experience.


The useful pattern is to separate:


  • Control plane: tenant policy, allowed assets, API keys, usage.

  • Session plane: the actual realtime avatar session, created from approved parameters.


That means your web app, backend job, or agent runtime can all request sessions, but none of them can bypass the tenant’s approved face, outfit, or voice sets. If you later add customer-managed embeds, you can still keep the same enforcement model: the embed can select among tenant-approved options, while your backend retains final authority.


Protoface: where the platform boundary helps


Protoface is useful here because it already gives you the main surfaces you need to keep policy on the server side: a REST API for session creation, a Python SDK for backend integration, and a LiveKit Agents plugin when you want to attach a video face to an existing voice agent. In other words, you can keep avatar customization in your application logic and use the realtime media layer only after the request has been validated.


For a LiveKit voice agent, the plugin approach is the cleanest mental model: your agent decides what it is allowed to say and which tenant policy applies; the avatar layer renders the approved presentation. The integration itself stays narrow, which is exactly what you want in a multitenant system. If you’re working from Python, the SDK is the same idea in library form: create or manage avatars and sessions after policy checks, not before. The documentation at docs.protoface.com is the right place to confirm the exact request fields and session objects.


from protoface import Client

print(session)
from protoface import Client

print(session)
from protoface import Client

print(session)


That code is intentionally illustrative. The important thing is the architectural boundary: your application owns authorization and asset selection; the avatar service executes the approved session.


Operational gotchas that matter in production


Once you ship this, the bugs you’ll see are usually not in rendering; they’re in governance and drift.


  • Stale policy caches: if you cache tenant rules, add a short TTL or explicit invalidation when admins update approved assets.

  • Asset deprecation: never delete an outfit or voice without checking whether active tenants still reference it.

  • Audit logs: store who changed the tenant policy and when, plus the session parameters that were actually approved.

  • Fallback behavior: define a deterministic default when a requested asset is missing, but only from within the allowed set.

  • Billing alignment: if quality tier affects cost, make sure the chosen tier is also part of the validated session record.


One good rule: if you cannot answer “why did this session use that voice?” from logs alone, your policy model is too loose.


Conclusion


To lock down avatar customization in a multitenant platform, treat outfit, face, and voice as policy-controlled resources, not as client-side preferences. Keep tenant rules server-side, validate combinations at session creation, and only pass approved values into the realtime runtime. That gives you predictable branding, cleaner audits, and fewer production surprises.


If you’re implementing this now, start with a tenant whitelist model, wire it into your session creation path, and test the failure cases as thoroughly as the happy path. The public docs at docs.protoface.com are the best place to verify the current API shape, and the relevant quickstarts on GitHub are useful if you want to see how session creation and agent integration fit together in practice.

Add a face to your AI.

No credit card needed.

Add a face to your AI.

No credit card needed.

Add a face to your AI.

No credit card needed.