Documentation / SDK and API
Integrating in your product
What to decide when you embed Seshat in a backend, a desktop app or an internal platform: clients, sessions, credentials, sandboxing and storage.
Embedding Seshat in a script is a few lines. Embedding it in a product that serves several people is a set of decisions. This page lists them.
Clients and sessions
A Client holds the provider connection, the tool registry and shared services. A Session holds one conversation.
| You are building | Use |
|---|---|
| A desktop or CLI app for one user | One client for the life of the app, one session per conversation |
| A server for many users | A client per set of credentials and settings (cached if creation is costly), a session per conversation, never shared between users |
| A batch or automation job | client.Ask for a single prompt, or a workflow |
Always call Close() on a session when the conversation ends, and on the client when you are done with it.
Per-request state
Several settings change from one request to the next. Do not store them on a shared client.
- Prompt bridge.
client.SetPromptFnchanges state shared by every turn on that client. If a client serves concurrent turns, attach the bridge to the request’s context instead:
import "github.com/KPO-Tech/seshat/pkg/types"
ctx = types.WithPromptFn(ctx, func(ctx context.Context, req types.PromptRequest) (types.PromptResponse, error) {
return ask(req) // goes to this user's connection
})
resp, err := session.SubmitMessage(ctx, text)
- Web search runner. Same idea with
types.WithWebSearchRunner(ctx, fn). - Working directory. Set
WorkingDirin the config, orsession.SetWorkingDirectory(path). Give each tenant their own folder. - User identity. Set
UserIDso plan documents are stored against the right person.
Credentials
Do not put one global key in the config for a multi-user product. Implement a CredentialResolver that looks up the key of the current user and provider. See Providers and authentication.
Run commands safely
The bash tool is always available and can run anything the host user can. For a multi-user or server deployment, that must be contained:
cfg.RequireSandbox = true // refuse to run commands when no OS sandbox is available
cfg.SandboxKind = sdk.SandboxKindDocker
| Setting | Effect |
|---|---|
SandboxKindLocal (default) | Landlock on Linux. Unconfined elsewhere unless RequireSandbox is set |
SandboxKindDocker | Commands run in a persistent Docker container. If Docker is not reachable when the client starts, it falls back to local with a logged warning |
RequireSandbox | The bash tool refuses to run when no sandbox is available, instead of running unconfined |
sdk.SandboxAvailable() tells you whether an OS-level sandbox exists on this host.
Secrets are removed from the environment of the commands the model runs. See Security and trust.
Storage
| Setting | Purpose |
|---|---|
PersistSessions, SessionStorageDir, SessionSQLitePath | Where conversations are saved (local files and SQLite by default) |
SessionStore / SessionBackend | Your own storage for sessions, to keep them in your database. Implement the SessionStore interface |
ArtifactStore, StorageConfig | Where files produced by the agent are kept |
StorageGCEnabled, StorageGCInterval | Cleanup of expired artifacts |
client.GetSessionStore() and client.GetArtifactStore() give you the stores in use.
Observe and control
SetProgressFn,SetResponseChunkFnandSetRuntimeEventFnfeed your interface. See Streaming, events and hooks.AddToolHook,RegisterHookandPreToolHookslet you audit or block actions.GetMonitoring()returns the monitoring system whenEnableMonitoringis on.MaxTurns,TurnTokenBudgetandMaxConsecutiveDenialsbound what one request can spend.
Checklist before you ship
- Credentials come from a resolver, not a shared key.
RequireSandboxis on, or commands are contained another way.- Each tenant has its own working directory and sessions.
- The prompt bridge is attached per request, not stored on a shared client.
- Limits are set (
MaxTurns, token budget). - Hooks log or block what your policy forbids.
- Sessions and clients are closed.
Updated on 2026-10-07