Request Pipeline
Build a request from a provider profile and prompt DTO. For Unity runtime components, use a coroutine handle; for asynchronous editor or service workflows, create a DTO-only snapshot on the main thread and await the request.
Runtime coroutine with cancellation
using BekaForge.AIProviders.Runtime;
using UnityEngine;
public sealed class NpcReply : MonoBehaviour
{
[SerializeField] private LlmProviderDefinitionBase provider;
private PromptCoroutineHandle active;
public void Request(string playerLine)
{
if (active != null) return;
var prompt = LlmPromptRequest.CreateWithSystemPrompt(
"Reply as a concise game character.", playerLine,
temperature: 0.6f, maxTokens: 160);
PromptCoroutineHandle requestHandle = null;
requestHandle = AiProvidersService.BeginPromptCoroutine(provider, prompt,
result =>
{
if (active != requestHandle) return;
if (result.Success) Debug.Log(result.ResponseText);
else Debug.LogError($"{result.Error}: {result.Diagnostic?.hint}");
active = null;
});
active = requestHandle;
StartCoroutine(requestHandle.Coroutine);
}
private void OnDisable()
{
var requestHandle = active;
active = null;
requestHandle?.Cancel();
}
}
BeginPromptCoroutine returns a PromptCoroutineHandle. Run its Coroutine through a live MonoBehaviour and call Cancel() if the component or request is no longer needed.
Async execution from a snapshot
using System.Threading;
using System.Threading.Tasks;
using BekaForge.AIProviders.Runtime;
public sealed class SummaryRequest
{
private readonly LlmProviderDefinitionBase provider;
public SummaryRequest(LlmProviderDefinitionBase provider) => this.provider = provider;
public async Task RunAsync(
CancellationToken cancellationToken)
{
var prompt = LlmPromptRequest.CreateUserOnly("Summarize this scene.");
if (!AiProvidersService.TryBuildExecutionSnapshot(
provider, prompt, out var snapshot, out var error))
{
return new AiProvidersService.PromptResult(false, string.Empty, error);
}
return await AiProvidersService.SendPromptAsync(snapshot, cancellationToken);
}
}
Call the snapshot builder on Unity's main thread; it reads provider configuration. The async method returns a nested AiProvidersService.PromptResult, so the caller owns presentation and cancellation.
Call TryBuildExecutionSnapshot on Unity's main thread because it reads provider configuration. The returned snapshot contains request data rather than live Unity objects and can then be passed to SendPromptAsync.
Streaming
using System.Text;
using BekaForge.AIProviders.Runtime;
using UnityEngine;
public sealed class StreamedNpcReply : MonoBehaviour
{
[SerializeField] private LlmProviderDefinitionBase provider;
private readonly StringBuilder received = new StringBuilder();
private PromptCoroutineHandle active;
public void Request(string playerLine)
{
if (active != null) return;
lock (received) received.Clear();
var prompt = LlmPromptRequest.CreateUserOnly(playerLine, maxTokens: 160);
PromptCoroutineHandle requestHandle = null;
requestHandle = AiProvidersService.BeginStreamPromptCoroutine(provider, prompt,
onDelta: delta =>
{
if (active != requestHandle) return;
lock (received) received.Append(delta);
},
onCompleted: result =>
{
if (active != requestHandle) return;
if (result.Success) Debug.Log(received.ToString());
else Debug.LogError(result.Error);
active = null;
});
active = requestHandle;
StartCoroutine(requestHandle.Coroutine);
}
private void OnDisable()
{
var requestHandle = active;
active = null;
requestHandle?.Cancel();
}
}
For HTTP profiles, streaming supports OpenAI-compatible server-sent events (including OpenAI and DeepSeek) and Ollama newline-delimited JSON. Gemini and Custom JSON do not currently advertise streaming support. The editor-only Codex and Claude Code transports also expose streamed deltas through their local tools. Check the selected provider's SupportsStreaming value before enabling a streaming UI.
Timeouts, retries, and results
AiProvidersService.RequestOptions exposes timeout seconds, retry count, and retry delay. Provider assets also expose reliability settings used when creating default options. Transient failures use exponential backoff with jitter. A provider’s positive Retry-After interval is honored without truncating it to 60 seconds; long waits remain cancellable. Authentication errors and malformed requests fail without transient retries. Inspect AiProvidersService.PromptResult.Error and its Diagnostic.hint to show an actionable message.
Response handling
Each provider parses its supported response shape and extracts text. Custom JSON profiles require a response-text path that matches the endpoint's actual JSON. Do not assume an arbitrary API response can be normalized automatically.
TrySendPrompt blocks the calling thread and is marked obsolete. Prefer the cancellable coroutine path for runtime or the snapshot plus async path for editor workflows.