TryllAgentComponent¶
Type: MonoBehaviour
Namespace: Tryll.Client
Source: Runtime/TryllAgentComponent.cs
Manages one TryllAgent lifetime on a GameObject. Drop it on any
GameObject to get an agent that connects, creates itself, and fires UnityEvents as tokens
arrive — no code required.
Inspector fields¶
Advanced variable is overridden (left checkbox ticked) to true.| Field | Type | Default | Description |
|---|---|---|---|
WorkflowAsset |
TryllWorkflowAsset |
— | Required. Workflow graph asset to use. CreateAgent fails if this is unset. Author the graph as a TryllWorkflowAsset (Create ▸ Tryll ▸ Workflow Asset). To build a graph in code without a component, use TryllGraphBuilder and TryllClient.RequestCreateAgentAsync. |
EnableDiagnostics |
bool |
false |
When true, the server includes LLM diagnostic info in TurnComplete payloads. |
MaintainDialogueHistory |
bool |
true |
When true (default) the agent keeps its full dialogue history across turns. Set false for a stateless agent whose history is discarded after each turn — for classification/routing agents that should not store or project prior turns. |
KvCacheInitialization |
TryllKvCacheInitialization |
AllocateOnly |
Choose AllocateOnly, Prefill, or DeferAllocation for eligible language-model contexts at creation. |
AutoCreateOnConnect |
bool |
true |
Automatically calls CreateAgent() when the session is ready (or when this component is enabled while already session-ready). |
Speaker |
TryllSpeaker |
— | Optional. Plays streaming TTS audio for this agent. When it is null and the graph speaks, CreateAgent uses the TryllSpeaker already on this GameObject, else adds one. Read at CreateAgent; a later change applies on the next CreateAgent. Leave null (and have no TTS nodes) to ignore TTS audio. |
Voice |
TryllVoiceProfile |
— | The agent's voice: TTS model, speaker or reference clip, speed, language, visemes and delivery modes. Required when the workflow has a Speak or GenerateAndSpeak node: without it CreateAgent fails with AgentVoiceRequired (3025), and the Inspector shows the same error. Ignored (and no TTS model is loaded) when the workflow does not speak. Read at CreateAgent; set it from code before creation when spawning characters at runtime. Change a live agent's voice with SetVoiceAsync. |
OverrideVoiceDelivery / VoiceDelivery |
bool / string |
false / neutral |
Per-agent override of the Voice profile's default delivery. The Inspector presents Voice Delivery as a checkbox and dropdown (neutral plus the assigned profile's modes). It is copied into CreateAgent without modifying the shared profile; changing it while an agent is live applies immediately. |
VariableOverrides |
List<TryllVariableOverride> |
empty | Per-instance initial-value overrides for variables declared on the workflow (Material-Instance pattern). The custom Inspector shows one optional row per declared variable — checkbox, read-only name, typed value — rather than a free-form list. Stale serialized entries (renamed/removed declarations) appear in a warning foldout and are skipped at CreateAgent with a Debug.LogWarning. |
Variable Overrides Inspector¶
For each variable declared on the WorkflowAsset, the Inspector draws:
- Override checkbox — when checked, this component's value replaces the declaration's initial value at
CreateAgent(and, in Play Mode, updates the live agent mirror — see below). - Name — read-only, taken from the declaration.
- Value — the type-appropriate editor (int / float / string / bool / string-set). Disabled until the override is checked; enabling seeds the field from the workflow default.
Only enabled overrides are stored as active sparse entries. Disabling an override keeps the authored value on the component (so re-enabling restores it) but clears the override flag.
Live agent (Play Mode or Tryll Chat): editing an override row updates Agent.Variables immediately (local mirror) whenever HasAgent is true. The wire flush stays deferred — the update is sent before the next SendMessage / Resume / ChangeParams. Unchecking an override assigns the workflow declaration default (not Reset(), which would restore the CreateAgent-time merged initial). A Flush Now button under Live Agent — Variables calls FlushIfDirty for debugging (useful before the next chat turn).
Public API¶
// Runtime state
public TryllAgent Agent { get; }
public bool HasAgent { get; }
public TryllSpeaker Speaker { get; set; }
public TryllVoiceProfile Voice { get; set; }
public bool OverrideVoiceDelivery { get; set; }
public string VoiceDelivery { get; set; }
// Actions
public async void CreateAgent();
public void DestroyAgent();
public new void SendMessage(string text);
public void Cancel(TryllCancelMode mode = TryllCancelMode.StopAndKeep);
public void ChangeParams(string nodeName, TryllNodeParamsBase @params,
Action<TryllError> onComplete = null);
public void Resume(string resumeNode = "", Action<TryllError> onComplete = null);
public void PrefillKvCache();
public void EvictKvCache();
public void GetKvCacheStatus();
public void AppendInteractions(IReadOnlyList<TryllDialogInteraction> interactions);
public void RemoveInteractionsFromEnd(int count);
public void ExportDialog();
public void ImportDialog(
TryllDialogSnapshot snapshot,
TryllDialogCompatibility compatibility = TryllDialogCompatibility.Strict);
public void SaveDialog(string path, string saveId);
public void LoadDialog(string path,
TryllDialogCompatibility compatibility = TryllDialogCompatibility.Strict);
public void RegisterTool(string toolName, Func<TryllToolCall, string> handler);
public void RegisterTool(string toolName, Func<TryllToolCall, Task<string>> handler);
public TryllNodeParamsBase GetNodeParamsBaseline(string nodeName);
// Voice (protocol v27)
public Task<TryllError> SetVoiceAsync(TryllVoiceProfile profile);
public Task<TryllError> SetDeliveryModeAsync(string mode, float intensity = 1f);
Per-agent Variables are reached through the agent handle:
agentComponent.Agent.Variables (a TryllAgentVariables
mirror). Agent is null until OnAgentCreated has fired.
CreateAgent is ignored when HasAgent is already true. On success it populates Agent
and fires OnAgentCreated. On failure it fires OnError and logs to the console.
SendMessage fires OnError and logs a warning if no agent is ready.
Cancel cooperatively stops the in-flight turn (OnTurnComplete with
TryllTurnStatus.Cancelled). No-op if no agent/turn is active.
ChangeParams / Resume complete via their result UnityEvents
(OnParamChanged / OnResumed) and the optional per-call callback — exactly once
per call. When no agent is ready they report InvalidAgentId (3001) through both
channels immediately. ChangeParams is allowed while idle or paused (rejected
with AgentBusy only while a turn is actively running between pauses).
GetNodeParamsBaseline returns a deep copy of the last authored params for the
named node, or null if no agent is ready / the name is unknown. The returned
object is already a clone — mutate it in place, then send via ChangeParams.
KV-cache operations are idle-only. Their result is aggregate status; sending after eviction restores eligible contexts automatically. This component exposes no status UI — use the result events below in your own UI if needed.
AppendInteractions / RemoveInteractionsFromEnd mutate scripted dialog
history without running the graph. Strict idle-only — rejected with
AgentBusy while a turn is running, paused, or during a KV-cache operation.
See Seed and edit dialog history.
ExportDialog captures the complete dialog into a TryllDialogSnapshot;
ImportDialog replaces the complete dialog. Both are strict idle-only.
The component reports completion through OnDialogExported /
OnDialogImported. Tryll does not write a save file.
SaveDialog / LoadDialog persist the same snapshot to a path resolved
against the server's process storage root and carry a caller save_id (the server stamps saved_at_ms).
Completion is OnDialogSaved / OnDialogLoaded. See
Save and Load Agent State.
SetVoiceAsync replaces the live agent's voice and, on success, makes the profile this
component's Voice, so a re-created agent keeps it. It is admitted while the agent is idle
or paused; a running turn rejects it with AgentBusy (3004), and a profile the model
cannot use with InvalidVoiceProfile (3023), keeping the old voice. With no agent yet it
only stores the profile for the next CreateAgent and returns Ok; while a create is in
flight it returns AgentBusy.
SetDeliveryModeAsync switches the delivery mode (a mode name from the voice profile, or
the built-in "neutral"). It is accepted at any time, including mid-turn, and applies from
the next sentence. intensity (0–1) scales the mode where the model can use it. Errors:
UnknownDeliveryMode (3024), AgentVoiceRequired (3025) when the agent has no voice,
InvalidAgentId when no agent is ready.
RegisterTool has a synchronous and an async (Task<string>) overload.
A complete paused batch auto-resumes only after every handler finishes on
the main thread.
Events¶
The UnityEvent rows wire up in the Inspector or with AddListener. The
NodeEvent rows (ToolCallNotification through NodeEvent) are C# events:
subscribe in code. They have no agent id — this component is the agent.
TryllClient keeps the all-agents versions. TryllAgent exposes the same
seven events for an agent you created without a component. A typed subscriber
on this component suppresses this component's NodeEvent for that event, and
does not suppress TryllClient.NodeEvent.
| Event | Signature | Description |
|---|---|---|
OnAnswerText |
(string nodeName, string text, bool isDelta, bool isFinal) |
Fired for each token chunk. nodeName attributes the producing workflow node; isDelta=true when the chunk is a streaming delta; isFinal=true on the last chunk of the turn. |
OnTurnComplete |
(TryllTurnStatus status, string debugInfo, int tokensGenerated) |
Fired once per turn after the last OnAnswerText. debugInfo is non-empty only when EnableDiagnostics is true. |
OnError |
(TryllError error) |
Fired on any agent-level error. |
OnAgentCreated |
UnityEvent |
Fired when CreateAgent() completes successfully. |
OnAgentDestroyed |
UnityEvent |
Fired when the agent is destroyed (by this component, by the server, or on disconnect). |
OnParamChanged |
(TryllError error) |
Fired when a ChangeParams request completes. Check error.IsOk — TryllError is a value type (success is not null). |
OnResumed |
(TryllError error) |
Fired when a Resume request completes. Check error.IsOk. Failures include AgentNotPaused (3012) and UnknownNode (3005). |
OnKvCachePrefilled |
(TryllKvCachePrefillResult result, TryllError error) |
Fired after a prefill request. TryllKvCachePrefillResult extends TryllKvCacheStatus with ContextsCreated, TokensDecoded, and TokensReused. Listeners must take this exact type. |
OnKvCacheEvicted |
(TryllKvCacheEvictResult result, TryllError error) |
Fired after an eviction request. TryllKvCacheEvictResult extends TryllKvCacheStatus with ContextsEvicted. Listeners must take this exact type. |
OnKvCacheStatus |
(TryllKvCacheStatus result, TryllError error) |
Fired after an aggregate status request. |
OnInteractionsAppended |
(uint count, TryllError error) |
Fired when AppendInteractions completes. count is appended_count from the server. |
OnInteractionsRemoved |
(uint count, TryllError error) |
Fired when RemoveInteractionsFromEnd completes. count is removed_count. |
OnDialogExported |
(TryllDialogSnapshot snapshot, TryllError error) |
Fired when ExportDialog completes. Encode a successful snapshot with ToFlatBufferBytes. |
OnDialogImported |
(TryllDialogImportResult result, TryllError error) |
Fired when ImportDialog completes. The result contains the restored interaction count and any compatibility warnings. |
OnDialogSaved |
(TryllDialogFileSaveResult result, TryllError error) |
Fired when SaveDialog completes. |
OnDialogLoaded |
(TryllDialogFileLoadResult result, TryllError error) |
Fired when LoadDialog completes. |
ToolCallNotification |
event Action<string, string> |
(toolName, argumentsJson) for this agent. |
ToolCallNotificationWithId |
event Action<string, string, string> |
(callId, toolName, argumentsJson). Use the id when resuming with a result. |
ToolCallDetailed |
event Action<TryllToolCall> |
Node name and disposition included. A subscriber suppresses NodeEvent for that call. |
IntentClassified |
event Action<TryllIntentClassification> |
Embedding ClassifyIntent result. The payload has no agent id. |
IntentLlmClassified |
event Action<TryllIntentLlmClassification> |
ClassifyIntentLLM result. The payload has no agent id. |
Paused |
event Action<string, string> |
(nodeName, pendingExit). This agent's turn paused. |
NodeEvent |
event Action<string, string, IReadOnlyList<KeyValuePair<string, string>>> |
(nodeName, eventType, kvPairs). Generic fallback when no typed listener is bound here. |
Lifetime and ownership¶
- The component owns its agent. It calls
Agent.Dispose()inOnDisableandOnDestroy. - Do not retain the
Agentreference beyond the component's lifetime. - If you need an agent that outlives the component, create it directly via
TryllClient.RequestCreateAgentAsyncand manage its lifetime yourself. - On disconnect the component clears its local state without sending a
DestroyAgentwire message (the TCP connection is gone).
See also¶
TryllClient— singleton session managerTryllWorkflowAsset— asset that stores a graphTryllVoiceProfile— the agent's voiceTryllAgent— the raw agent handleTryllAgentVariables— the typed variables mirror- Agent Variables
- Change Agent Parameters at Runtime
- Pause and Resume a Turn
- Manage an Agent's KV Cache
- Save and Load Agent State
- Build a chat agent with a graph
- Stream answers to your UI