Chat History¶
SMG supports multiple storage backends for persisting the conversations, conversation items, and stored responses behind the Responses and Conversations APIs, for analytics, debugging, and compliance.
Overview¶
Multiple Backends¶
Choose from in-memory, PostgreSQL, Redis, or Oracle based on your requirements.
Conversation Tracking¶
Store complete conversation history including messages, tool calls, and reasoning.
Configurable Retention¶
Redis entries expire after --redis-retention-days (default 30 days). The other backends keep data until it's deleted (the in-memory backend, until the gateway restarts).
Backend Comparison¶
| Backend | Use Case | Persistence | Scalability |
|---|---|---|---|
memory |
Development, testing | Process lifetime | Single instance |
none |
Stateless deployments | None | N/A |
postgres |
Production, self-hosted | Durable | High |
redis |
Caching, ephemeral storage | Configurable TTL | High |
oracle |
Enterprise, OCI deployments | Durable | High |
Configuration¶
Backend Selection¶
smg --history-backend <backend> [backend-specific options]| Option | Default | Description |
|---|---|---|
--history-backend |
memory |
Storage backend: memory, none, oracle, postgres, redis |
Memory Backend¶
The default in-process storage. Suitable for development and testing.
smg --history-backend memory✓ Advantages¶
- Zero configuration
- Fast access
- No external dependencies
✗ Limitations¶
- Data lost on restart
- Not shared across instances
- Memory grows with conversations
None Backend¶
Disables history storage entirely. Use for stateless deployments where persistence isn't needed.
smg --history-backend noneUse when: Privacy requirements prohibit storing conversations, or external systems handle logging.
PostgreSQL Backend¶
Production-ready storage with PostgreSQL.
Configuration Options¶
| Option | Default | Description |
|---|---|---|
--postgres-db-url |
- | PostgreSQL connection URL |
--postgres-pool-max-size |
16 |
Maximum connection pool size |
Connection URL Format¶
postgres://[user[:password]@]host[:port]/database[?param=value]The scheme can also be postgresql://. SMG requires a host and a database name.
Examples¶
Basic Connection¶
smg --history-backend postgres \
--postgres-db-url "postgres://user:password@localhost:5432/smg"With a Connect Timeout¶
smg --history-backend postgres \
--postgres-db-url "postgres://user:password@db.example.com:5432/smg?connect_timeout=30"Redis Backend¶
High-performance caching with optional persistence and TTL-based retention.
Configuration Options¶
| Option | Default | Description |
|---|---|---|
--redis-url |
- | Redis connection URL |
--redis-pool-max-size |
16 |
Maximum connection pool size |
--redis-retention-days |
30 |
Data retention in days (-1 for persistent; write it as --redis-retention-days=-1, since the Rust CLI rejects a separate -1 argument) |
Connection URL Format¶
redis://[:password@]host[:port][/db]Examples¶
Basic Connection¶
smg --history-backend redis \
--redis-url "redis://localhost:6379"With a Password¶
smg --history-backend redis \
--redis-url "redis://:password@redis.example.com:6379"Persistent Storage¶
smg --history-backend redis \
--redis-url "redis://localhost:6379" \
--redis-retention-days=-1Oracle Backend¶
Enterprise-grade storage using Oracle Autonomous Database.
Configuration Options¶
| Option | Environment Variable | Default | Description |
|---|---|---|---|
--oracle-wallet-path |
ATP_WALLET_PATH |
- | Path to ATP wallet directory |
--oracle-tns-alias |
ATP_TNS_ALIAS |
- | TNS alias from tnsnames.ora |
--oracle-dsn |
ATP_DSN |
- | Direct connection descriptor |
--oracle-user |
ATP_USER |
- | Database username |
--oracle-password |
ATP_PASSWORD |
- | Database password |
--oracle-external-auth |
ATP_EXTERNAL_AUTH |
false |
Use external (OS) authentication instead of username/password; leave --oracle-user and --oracle-password unset |
--oracle-pool-min |
ATP_POOL_MIN |
1 |
Must be at least 1 and at most --oracle-pool-max. The pool opens connections on demand and doesn't hold a minimum open |
--oracle-pool-max |
ATP_POOL_MAX |
16 |
Maximum connection pool size |
--oracle-pool-timeout-secs |
ATP_POOL_TIMEOUT_SECS |
30 |
How long a request waits for a free pooled connection, in seconds. Must be greater than 0 |
--oracle-dsn takes precedence: with a DSN, SMG ignores the wallet and TNS alias. The Python launcher (smg launch from pip, and the container image) names two of these flags differently, --oracle-username and --oracle-connect-descriptor, and uses the TNS alias when both an alias and a DSN are given. See Python Launcher Differences.
Examples¶
Using ATP Wallet¶
smg --history-backend oracle \
--oracle-wallet-path /path/to/wallet \
--oracle-tns-alias mydb_high \
--oracle-user admin \
--oracle-password "$ORACLE_PASSWORD"Using Direct DSN¶
smg --history-backend oracle \
--oracle-dsn "(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=db.example.com)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=myservice)))" \
--oracle-user admin \
--oracle-password "$ORACLE_PASSWORD"Schema Migrations¶
At startup, the PostgreSQL and Oracle backends create their tables if they don't exist, then compare the database's recorded schema version (the _schema_versions table) with the migrations SMG ships. SMG applies pending migrations only when auto-migration is on. Otherwise it refuses to start and prints the SQL to apply by hand. A new, empty database has pending migrations too, so turn auto-migration on for the first start:
DB_AUTO_MIGRATE=true smg launch --history-backend postgres \
--postgres-db-url "postgres://user:password@localhost:5432/smg"DB_AUTO_MIGRATE=true (or 1) turns it on when no --schema-config file sets auto_migrate. In a schema config file, auto_migrate: true turns it on, and version: <n> marks migrations up to <n> as already applied. Redis and the in-memory backend have no migrations. See Schema Migrations.
What Gets Stored¶
Conversations¶
Container for a sequence of interactions:
- Conversation ID
- Creation timestamp
- Metadata (the key-value object the client attaches)
Conversation Items¶
Individual items within a conversation:
| Type | Description |
|---|---|
| Messages | User and assistant messages with content |
| Reasoning | Model reasoning/thinking steps |
| Tool Calls | Tool invocations and results |
| MCP Calls | MCP server interactions |
| Function Calls | Function calling results |
Responses¶
Complete response records including:
- Input items
- Output (model response)
- Tool calls executed
- Model information
- Timestamps and metadata
- Token usage
Recommended Configurations¶
Production (Self-Hosted)¶
PostgreSQL for durable storage.
smg --history-backend postgres \
--postgres-db-url "postgres://smg:$DB_PASSWORD@postgres:5432/smg" \
--postgres-pool-max-size 32Enterprise (OCI)¶
Oracle for enterprise deployments.
smg --history-backend oracle \
--oracle-wallet-path /etc/smg/wallet \
--oracle-tns-alias smg_high \
--oracle-user smg_app \
--oracle-password "$ATP_PASSWORD" \
--oracle-pool-max 32Caching Layer¶
Redis for high-performance ephemeral storage.
smg --history-backend redis \
--redis-url "redis://:$REDIS_PASSWORD@redis.example.com:6379" \
--redis-retention-days 7 \
--redis-pool-max-size 64Troubleshooting¶
| Symptom | Cause | Solution |
|---|---|---|
| Connection timeouts | Slow network | Increase pool timeout |
| Pool exhaustion | High concurrency | Increase pool size |
| Data not persisting | Wrong backend | Verify --history-backend setting |
| Redis data expiring | TTL too short | Increase --redis-retention-days |
Pool Configuration¶
# PostgreSQL
--postgres-db-url "postgres://...?connect_timeout=30"
--postgres-pool-max-size 64
# Oracle
--oracle-pool-timeout-secs 60
--oracle-pool-max 64
# Redis
--redis-pool-max-size 64