Skip to main content

Profile Selection

Profiles name the models and settings the developer's server offers.

By default, every user can request every profile. Calls for intents the developer has mapped use the mapped profile; other calls use the requested profile, or the default profile when none is requested.

A profile authorizer lets the developer decide which profiles each user may request, typically from the user's plan. It filters the profile list clients see, and rejects requests for any other profile.

Restrict which profiles a user may use​

Implement IAIProfileAuthorizer and return the candidate profiles the user may use:

PlanProfileAuthorizer.cs
using Reveal.Sdk;
using Reveal.Sdk.AI;

public sealed class PlanProfileAuthorizer : IAIProfileAuthorizer
{
private readonly IPlanStore _plans;

public PlanProfileAuthorizer(IPlanStore plans) => _plans = plans;

public async ValueTask<IReadOnlyCollection<string>> GetAuthorizedProfilesAsync(
IRVUserContext user, IReadOnlyCollection<string> candidateProfiles, CancellationToken cancellationToken)
{
// Retrieve the plan from custom storage
var plan = await _plans.GetPlanAsync(user.UserId, cancellationToken);
return plan switch
{
"enterprise" => candidateProfiles,
"pro" => candidateProfiles.Where(p => p != "premium").ToList(),
_ => candidateProfiles.Where(p => p == "default").ToList(),
};
}
}
Program.cs
builder.Services.AddRevealAI()
// providers and profiles
.AddProfileAuthorizer<PlanProfileAuthorizer>();

The authorizer is registered as a singleton. Only one authorizer is supported; registering a second one replaces the first.

The authorizer drives both the profile list and request validation:

  • GET /api/reveal/ai/profiles, and client.ai.profiles.list() in the client SDK, return only the profiles the user may use, so a model picker shows only those.
  • A request for any other profile fails with HTTP 403 and the code ai.profile_not_allowed. A request for a profile that doesn't exist fails with HTTP 400 and ai.profile_not_found. Reveal never falls back to another profile silently, except for requests that still use the deprecated model field instead of profile: an unknown name there falls back to the default profile and logs a warning.
  • The candidates include dynamic (BYOK) profiles. An authorizer that keeps only specific names, like the free-plan branch above, hides them too.
  • The developer's intent mappings and default profile are the developer's own decisions, so the authorizer doesn't filter them. It only governs what clients may request.
  • In Node.js and Java, a callback that throws or returns a malformed result denies every profile, and names that weren't among the candidates are ignored.