How the DuckDB Mirror and Quack Protocol Operate in agentsview

Agentsview stores session data in either a local DuckDB file (the "mirror") or a remote DuckDB instance exposed through the Quack protocol, with both modes sharing the same Store implementation but routing queries differently based on the connection kind.

The open-source agentsview project provides flexible storage backends for session data, supporting both local file-based storage and remote database connections. Understanding how the DuckDB mirror and Quack protocol operate is essential for configuring deployments that balance performance, durability, and distributed access. This article examines the source code implementation in the kenn-io/agentsview repository to explain the architectural differences and shared abstractions between these two storage modes.

Local DuckDB Mirror Storage

The DuckDB mirror implements a local file-based storage backend where session data persists to an on-disk DuckDB database. This mode is ideal for single-node deployments or CLI usage where network overhead is undesirable.

Opening the Database File

In internal/duckdb/connect.go, the Open function (lines 22-34) creates a SQLite-compatible DuckDB connection with specific constraints optimized for the mirror pattern:

// Open creates a new DuckDB connection with single-connection pooling
func Open(path string) (*sql.DB, error) {
    connector, err := duckdb.NewConnector(path, func(conn driver.Conn) error {
        // Configure thread count and other settings
        return nil
    })
    // Pool limited to 1 connection because DuckDB allows only one writer per file
    db := sql.OpenDB(connector)
    db.SetMaxOpenConns(1)
    return db, nil
}

The implementation deliberately limits the connection pool to a single connection because DuckDB enforces a single-writer policy per database file. This prevents concurrent write errors while maintaining read concurrency through the same connection.

Store Wrapper Implementation

The NewStore function in internal/duckdb/store.go (lines 37-44) wraps the *sql.DB connection produced by Open. All read-only queries—including queryDuckDBContext and queryDuckDBRowContext—execute directly against this local connection. When the CLI agentsview command initializes storage via NewStoreFromConfig (lines 84-92 in connect.go), it detects the absence of a remote URL and instantiates a local mirror instead.

Quack Protocol for Remote DuckDB

The Quack protocol enables agentsview to treat a remote DuckDB server as a virtual catalog, allowing SQL execution on the remote side while maintaining a local client interface. This mode supports distributed deployments where multiple agentsview instances share a central database.

Establishing the Client Connection

The openQuackClient function in internal/duckdb/connect.go (lines 71-106) handles the complex initialization sequence:

  1. URL Validation: ValidateQuackClientURL parses the Quack connection string
  2. In-Memory Instance: Creates a temporary local DuckDB instance to host the client
  3. Extension Loading: Installs and loads the quack extension
  4. Remote Attachment: Executes ATTACH ... AS agentsview_remote via quackAttachSQL (lines 30-38)
// quackAttachSQL builds the ATTACH statement with optional token authentication
func quackAttachSQL(url, token string) string {
    if token != "" {
        return fmt.Sprintf("ATTACH '%s' AS agentsview_remote (TOKEN '%s')", url, token)
    }
    return fmt.Sprintf("ATTACH '%s' AS agentsview_remote", url)
}

After attachment, the client switches to the remote catalog using USE agentsview_remote, making the remote database the default execution context.

Query Routing and Execution

The Store struct maintains a connectionKind flag that determines query routing. In internal/duckdb/store.go (lines 75-84), the query helpers check this flag:

  • Local mode (duckDBBaseConnection): Queries execute directly on s.duck
  • Quack mode (duckDBQuackClientConnection): SQL converts to literal strings via duckSQLWithArgs, then routes through quack.queryRemote:
// Quack path in queryDuckDBContext
rows, err := quack.queryRemote(ctx, sqlText, true)

The remote execution translates to SELECT * FROM agentsview_remote.query(?) (lines 14-18 in connect.go), where the parameter contains the original SQL statement to execute on the remote server.

Automatic Reconnection Handling

The Quack client implements resilient connection management through the reattachMu mutex and reattachLocked method. When queryRemote or execRemote detect a stale connection via isStaleQuackConnectionError, they automatically:

  1. Lock the reattachment mutex
  2. Detach the old catalog
  3. Re-run the ATTACH sequence
  4. Retry the failed query once

This mechanism ensures network transient failures do not require manual intervention or application restarts.

Security and Credential Redaction

The implementation includes comprehensive credential protection through RedactQuackURL and redactQuackClientErrorMessage (lines 52-78 in connect.go). These helpers identify sensitive URL parameters using isSecretURLQueryKey and strip credentials via redactQuackCredentialValue before logging, ensuring tokens and passwords never appear in error messages or logs.

Practical Implementation Examples

Opening a Remote Quack Store

import (
    "context"
    "go.kenn.io/agentsview/internal/duckdb"
    "log"
)

func main() {
    // URL format: quack://host[:port]?token=<token>
    store, err := duckdb.NewQuackStore("quack:tcp://127.0.0.1:8810", "my-secret-token", false)
    if err != nil {
        log.Fatalf("failed to attach Quack endpoint: %v", err)
    }
    defer store.Close()

    // Query execution automatically routes to remote DuckDB
    rows, err := store.QueryContext(context.Background(),
        "SELECT id, created_at FROM sessions LIMIT 5")
    if err != nil {
        log.Fatalf("query failed: %v", err)
    }
    defer rows.Close()
}

NewQuackStore sets connectionKind to duckDBQuackClientConnection, enabling transparent remote execution through the same API used for local mirrors.

Local Mirror Usage

// Local file path creates a mirror store
store, err := duckdb.NewStore("/var/lib/agentsview/data.duckdb")
if err != nil {
    log.Fatal(err)
}

// Identical API works for both storage modes
row := store.QueryRowContext(context.Background(),
    "SELECT COUNT(*) FROM messages")
var cnt int
if err := row.Scan(&cnt); err != nil {
    log.Fatal(err)
}

Handling Stale Connections (Internal Mechanism)

// Simplified excerpt from quackClient.queryRemote
rows, err := q.duck.QueryContext(ctx, "SELECT * FROM agentsview_remote.query(?)", sqlText)
if err != nil && retryStale && isStaleQuackConnectionError(err) {
    q.reattachMu.Lock()
    _ = q.reattachLocked(ctx) // Re-attach remote catalog
    q.reattachMu.Unlock()
    rows, err = q.duck.QueryContext(ctx, "SELECT * FROM agentsview_remote.query(?)", sqlText)
}

Summary

  • DuckDB Mirror: A local file-based storage mode using internal/duckdb/connect.go to create single-pooled connections, suitable for standalone deployments.
  • Quack Protocol: A remote attachment system using openQuackClient and quackAttachSQL to virtualize remote DuckDB servers as local catalogs (agentsview_remote).
  • Unified Interface: The Store abstraction in internal/duckdb/store.go routes queries based on connectionKind, supporting both modes through identical method signatures.
  • Resilience: Automatic reconnection via reattachLocked and isStaleQuackConnectionError detection ensures high availability for remote connections.
  • Security: Built-in redaction via RedactQuackURL prevents credential leakage in logs and error traces.

Frequently Asked Questions

What is the difference between the DuckDB mirror and Quack protocol in agentsview?

The DuckDB mirror stores session data in a local on-disk file with single-connection pooling, while the Quack protocol connects to a remote DuckDB server over the network using a virtual catalog attachment. Both implement the same Store interface, but the mirror executes queries locally whereas Quack serializes SQL to remote execution via queryRemote.

How does agentsview handle connection failures when using the Quack protocol?

The quackClient struct monitors for stale connection errors using isStaleQuackConnectionError. When detected, it acquires the reattachMu lock, detaches the old catalog, re-executes the ATTACH sequence through reattachLocked, and retries the failed query once. This process requires no application-level intervention.

Can I switch between local mirror and Quack protocol without changing application code?

Yes. The Store abstraction in internal/duckdb/store.go provides identical methods like QueryContext and QueryRowContext for both modes. The connectionKind flag (set to either duckDBBaseConnection or duckDBQuackClientConnection) determines routing internally, so applications using NewStore (local) or NewQuackStore (remote) receive the same interface.

How does agentsview protect Quack connection credentials?

All Quack URLs and tokens pass through RedactQuackURL and redactQuackClientErrorMessage before logging. These functions identify sensitive query parameters using isSecretURLQueryKey and mask values via redactQuackCredentialValue, ensuring that authentication tokens and passwords never appear in error messages or log files.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →