Using Spectron from Swift applications and agents.
The Spectron client is shipped alongside the SurrealDB Swift SDK in the surrealdb.swift package. It is a separate product that talks to Spectron's memory and knowledge API, built on Swift async/await and URLSession with a swappable HTTPClient for testing. The client is Sendable.
Installation
Add the Spectron product to your target's dependencies:
Authentication uses the Authorization: Bearer header on every request (handled by the client). Functionality is organised into three namespaces: documents, memory (sessions, entities, facts) and governance (scopes, principals, keys). Common operations are also exposed directly on the client.
Sessions bundle conversation turns and provide context for retrieval:
let session = try await memory.sessions.create(scope: ["user/tobie"])
_ = try await session.ingest(text: "I just got promoted to CTO", role: .user)
let ctx = try await session.context("What is Tobie's role?") let reply = try await myLLM.chat(system: ctx.context, user: userMessage) _ = try await session.ingest(text: reply, role: .assistant)
try await session.close()
Chat
Run the managed chat loop with context retrieval and persistence:
let reply = try await memory.chat("What do you know about me?", sessionId: session.id)
Stream responses incrementally over Server-Sent Events:
for try await chunk in try await memory.chatStream("Summarise what you know about me") { if chunk.done { print("\n[trace: \(chunk.traceId ?? "")]") } else { print(chunk.delta, terminator: "") } }
// API keys (the secret is returned only at creation) let minted = try await memory.keys.create(name: "ci", grants: ["org/anneal": ["read"]], ttlSeconds: 3600)
Delegation
Act as another principal by passing onBehalfOf:, which is sent as the X-Spectron-On-Behalf-Of header. Writes also carry an Idempotency-Key header for safe retry deduplication.
let docs = try await memory.documents.list(onBehalfOf: "agent:reader") let me = try await memory.whoami(onBehalfOf: "agent:reader")
Error handling
All failures throw SpectronError, whose kind maps the HTTP status to .base, .auth, .scope, .notFound, .validation, .rateLimit or .server:
do { _ = try await memory.documents.get("doc:missing") } catch let error as SpectronError where error.isNotFound { print(error.status, error.title) } catch let error as SpectronError where error.isRateLimit { print("retry after", error.retryAfter ?? 0, "seconds") }