# How the DuckDB Mirror and Quack Protocol Operate in agentsview

> Understand how Agentsview uses the DuckDB mirror and Quack protocol to store and retrieve session data locally or remotely, optimizing query routing for seamless operation.

- Repository: [Kenn Software/agentsview](https://github.com/kenn-io/agentsview)
- Tags: deep-dive
- Published: 2026-07-04

---

**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`](https://github.com/kenn-io/agentsview/blob/main/internal/duckdb/connect.go), the `Open` function (lines 22-34) creates a SQLite-compatible DuckDB connection with specific constraints optimized for the mirror pattern:

```go
// 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`](https://github.com/kenn-io/agentsview/blob/main/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`](https://github.com/kenn-io/agentsview/blob/main/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`](https://github.com/kenn-io/agentsview/blob/main/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)

```go
// 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`](https://github.com/kenn-io/agentsview/blob/main/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`:

```go
// 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`](https://github.com/kenn-io/agentsview/blob/main/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`](https://github.com/kenn-io/agentsview/blob/main/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

```go
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

```go
// 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)

```go
// 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`](https://github.com/kenn-io/agentsview/blob/main/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`](https://github.com/kenn-io/agentsview/blob/main/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`](https://github.com/kenn-io/agentsview/blob/main/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.