Skip to content

TryllClient

Type: MonoBehaviour (singleton)
Namespace: Tryll.Client
Source: Runtime/TryllClient.cs

Singleton MonoBehaviour that manages the TCP session to the Tryll server. Created automatically at game start by TryllClientModule via [RuntimeInitializeOnLoadMethod(BeforeSceneLoad)] — you do not add it to a scene yourself.

In Play mode it lives on a DontDestroyOnLoad GameObject. In the Editor outside Play mode the static helper EnsureEditorInstance() creates a hidden HideAndDontSave instance.


Connection settings

These are read from TryllRuntimeSettings on Awake.

Field Type Default
ServerHost string "127.0.0.1"
ServerPort int 9100

Public API

// Singleton access
public static TryllClient Instance { get; }

// Connection state
public bool  IsConnected { get; }
public ulong SessionId   { get; }

// Connection
public void Connect();
public void Disconnect();

// Session
public void CreateSession(TryllInferenceEngine engine,
                             string gameName = "",
                             TryllInferenceEngine sttEngine       = TryllInferenceEngine.Mock,
                             TryllInferenceEngine ttsEngine       = TryllInferenceEngine.Mock,
                             TryllInferenceEngine embeddingEngine = TryllInferenceEngine.Mock,
                             string storageDataFolder = "");   // relative storage/hotword paths resolve here

// Agent lifecycle — always check error.IsOk before using the agent
public Task<(TryllAgent agent, TryllError error)>
    RequestCreateAgentAsync(TryllGraphDescription graph, bool enableDiagnostics = false);

// Model management
public Task<(List<TryllModelInfo> models, TryllError error)> RequestListModelsAsync();
public void RequestDownloadModel(string modelName);
public void RequestLoadModel(string modelName);
public void RequestUnloadModel(string modelName);

// StringStorage (List / Map / Multimap)
public Task<TryllError> RequestCreateStringStorageAsync(string name, List<string> strings);
public Task<TryllError> RequestCreateStringStorageFromFileAsync(
    string name, string filePath, Tryll.StringStorageKind kind = Tryll.StringStorageKind.List);
public Task<TryllError> RequestCreateKeyedStringStorageAsync(
    string name, List<string> keys, List<string> values,
    Tryll.StringStorageKind kind = Tryll.StringStorageKind.Map);
public Task<TryllError> RequestDestroyStringStorageAsync(string name);

// EmbeddedStringStorage (RAG)
public Task<(EmbeddedStorageInfo info, TryllError error)>
    RequestCreateEmbeddedStringStorageAsync(string name, string configPath, string embeddingModel = "");
public Task<(EmbeddedStorageInfo info, TryllError error)>
    RequestCreateEmbeddedStringStorageFromStringsAsync(string name, List<string> strings, string embeddingModel);
public Task<TryllError> RequestDestroyEmbeddedStringStorageAsync(string name);

// Voice input (STT) — see the TryllVoiceInput handle for BeginUtterance/EndUtterance/…
public Task<(TryllVoiceInput voice, TryllError error)> CreateVoiceInputAsync(VoiceInputConfig cfg);

// GPU throttling — fire-and-forget, no response, safe to call every frame
public void SetInferenceThrottle(float level);

// Editor utility
public static TryllClient EnsureEditorInstance();

GPU throttling and background agents

SetInferenceThrottle tells the server how hard to yield the GPU back to your game — 0f = full speed (the default for a session that never calls it), 1f = maximum yielding. It is fire-and-forget: no request id, no response, nothing to await, so calling it from Update() is fine. It never changes what is generated, only how fast.

void Update()
{
    // Example policy: yield harder as your own frame time worsens.
    float pressure = Mathf.InverseLerp(11f, 20f, Time.smoothDeltaTime * 1000f);
    TryllClient.Instance.SetInferenceThrottle(pressure);
}

Agents nobody is waiting on should say so, so their inference is the first to give way:

var (agent, error) = await TryllClient.Instance.RequestCreateAgentAsync(
    graph, workload: Tryll.AgentWorkload.Background);

Everything else the server classifies from the graph itself, per turn — streamed Generate text is protected, spoken and buffered work absorbs the slack. See Wire Protocol and Server configuration.


Events

All events fire on the Unity main thread.

Event Signature Description
ConnectionChanged Action<bool> Connection state changed. Parameter: isConnected.
Error Action<TryllError> Session-level or unroutable error.
CreateSessionComplete Action<TryllError> Server acknowledged CreateSession.
DownloadProgress Action<string, ulong, ulong, float> (modelName, bytesDownloaded, totalBytes, percent 0–100) — streaming progress. totalBytes may be 0 when unknown.
DownloadComplete Action<string, bool, string> (modelName, success, error) — download finished or failed. error is empty on success.
LoadModelComplete Action<string, bool> (modelName, success)
UnloadModelComplete Action<string, bool> (modelName, success)
AgentDestroyed Action<ulong> (agentId) — server confirmed agent teardown.
ToolCallNotification Action<ulong, string, string> (agentId, toolName, argumentsJson)
IntentClassified Action<ulong, string, string, ulong, float> (agentId, intent, recordId, recordIndex, distance)
Paused Action<ulong, string, string> (agentId, nodeName, pendingExit) — the executor paused a turn between nodes (Pause node, or a ToolCall with a pausing disposition). See How to pause and resume a turn.
NodeEvent Action<ulong, string, string, IReadOnlyList<KeyValuePair<string,string>>> Generic fallback for unknown or unsubscribed typed events. (agentId, nodeName, eventType, kvPairs)
StringStorageChanged Action<string, bool> (name, isCreate)
EmbeddedStringStorageChanged Action<string, int, bool> (name, recordCount, isCreate)

EmbeddedStorageInfo

public struct EmbeddedStorageInfo
{
    public string Name;
    public uint   RecordCount;
    public uint   EmbeddingDim;
}

Lifecycle

  1. TryllClientModule creates the singleton at BeforeSceneLoad.
  2. Awake reads TryllRuntimeSettings and applies ServerHost / ServerPort.
  3. Call Connect() to open the TCP session (or enable Auto Launch Server in settings).
  4. Call CreateSession(...) to select the inference engine.
  5. Use RequestCreateAgentAsync or attach a TryllAgentComponent.
  6. Call Disconnect() when done, or let OnDestroy clean up on exit.

See also