daguito

package module
v0.5.8 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 15, 2026 License: MIT Imports: 18 Imported by: 0

README

Daguito

daguito (Go SDK)

Official Go SDK for the Daguito conversational AI platform — text, voice, image, audio, document and video agent flows.


Standard-library HTTP, github.com/coder/websocket for the streaming session. Go 1.22+. Mirrors the Python and TypeScript SDKs feature-for-feature.

go get github.com/daguitocontact-lang/go-sdk
import "github.com/daguitocontact-lang/go-sdk"

What's in the box

Symbol Use it for
RunWebhook One-shot HTTP call to a flow. Wait, get the result.
WebhookStreamSession Long-lived WebSocket. Streams tokens, node lifecycle, custom emits.
UploadFile Presigned upload for image / audio / document / video attachments.
session.RegisterTool Register OpenAI-style function tools the LLM can invoke on your code.
WebhookStreamOptions.Scope Server-enforced metadata filter for KB searches (data isolation).
KnowledgeSession Ingest + search a Knowledge Base with a sk_dgt_... org key.

Every WebSocket event is a typed struct delivered on session.Events() — switch on evt.Type and read the matching pointer.

Authentication

Surface Key shape Best for
Webhook sk_wh_... Server-to-server, your own backend, scripts
Knowledge Base sk_dgt_... Ingest + search against your own KB

Create both from the Daguito dashboard.

Quick start

One-shot webhook

ctx, cancel := context.WithTimeout(context.Background(), 90*time.Second)
defer cancel()

result, err := daguito.RunWebhook(ctx, daguito.WebhookRunInput{
    APIURL: "https://ingest.daguito.com",
    Token:  "sk_wh_...",
    Input:  map[string]any{"question": "What is the capital of France?"},
})
if err != nil {
    log.Fatal(err)
}
fmt.Println(result.Output)

Streaming a chat agent

session := daguito.NewWebhookStreamSession(daguito.WebhookStreamOptions{
    APIURL:    "https://ingest.daguito.com",
    WebhookID: "wh_abc123",
    Token:     "sk_wh_...",
})
if err := session.Connect(ctx); err != nil { log.Fatal(err) }
defer session.Close()

_ = session.Send(ctx, daguito.TextMessage("Hello!"), nil)

for evt := range session.Events() {
    switch evt.Type {
    case daguito.EventNodeToken:
        fmt.Print(evt.NodeToken.Text)
    case daguito.EventFlowCompleted:
        return
    case daguito.EventFlowFailed:
        log.Printf("failed: %s", evt.FlowFailed.Error)
        return
    }
}

Sending attachments

Pre-uploaded media key:

up, err := daguito.UploadFile(ctx, daguito.UploadInput{
    APIURL:    "https://ingest.daguito.com",
    WebhookID: "wh_abc123",
    Token:     "sk_wh_...",
    Kind:      daguito.MediaKindDocument,
    Path:      "/tmp/report.pdf",
})
if err != nil { log.Fatal(err) }

_ = session.Send(ctx, daguito.MediaKeyMessage(
    daguito.MediaKindDocument,
    up.MediaKey,
    up.MimeType,
    up.SizeBytes,
    "Summarize this report",
), nil)

Public image URL (no upload, fastest path):

_ = session.Send(ctx, daguito.ImageURLMessage("https://example.com/photo.jpg", "What's in this image?"), nil)

_ = session.Send(ctx, daguito.ImageMultiMessage(
    []string{"https://example.com/a.jpg", "https://example.com/b.jpg"},
    "Compare these two",
), nil)

Per-session scope (server-enforced KB filter)

When your KB holds data for many users / workspaces / documents, you want each chat to only see chunks tagged with the right key. Set Scope on the session — Daguito forces every KB search the agent makes to apply it as a metadata filter, server-side. The LLM never sees the values, so it can't widen the search or leak across tenants.

session := daguito.NewWebhookStreamSession(daguito.WebhookStreamOptions{
    APIURL:    "https://ingest.daguito.com",
    WebhookID: "wh_abc123",
    Token:     "sk_wh_...",
    Scope: map[string]any{
        "workspace_id": "ws_42",
        "document_id":  "doc_abc",
    },
})

Scope values must be primitives (string, int, float64, bool); arrays and maps are silently dropped at the wire boundary.

Client-side tools (function calling)

Tools registered on the session run locally — Go code, in your process — and their return value is fed back to the LLM as the tool result. Same shape as OpenAI function calling.

err := session.RegisterTool(
    daguito.ToolSpec{
        Name:        "get_weather",
        Description: "Get the current weather for a city.",
        Parameters: map[string]any{
            "type": "object",
            "properties": map[string]any{
                "city":  map[string]any{"type": "string"},
                "units": map[string]any{"type": "string", "enum": []string{"c", "f"}},
            },
            "required": []string{"city"},
        },
    },
    func(ctx context.Context, raw json.RawMessage) (any, error) {
        var args struct {
            City  string `json:"city"`
            Units string `json:"units"`
        }
        if err := json.Unmarshal(raw, &args); err != nil { return nil, err }
        data, err := myWeather.Fetch(ctx, args.City, args.Units)
        if err != nil { return nil, err }
        return map[string]any{"temp": data.Temp, "conditions": data.Summary}, nil
    },
)

Return an error to surface a failure to the LLM. Tools are merged with whatever the flow already declares server-side — the LLM picks the best fit.

Tool progress events (data-only)

When a server-side tool runs (KB search, media analysis, web search), the engine emits tool_progress events. They're data-only — no localised strings — so your client renders whatever copy/UI you want.

for evt := range session.Events() {
    if evt.Type != daguito.EventNodeEmit { continue }
    progress := daguito.ParseToolProgress(evt.NodeEmit)
    if progress == nil { continue }
    fmt.Printf("[%s] %s\n", progress.Tool, progress.Stage)
}

Knowledge Base

kb := daguito.NewKnowledgeSession(daguito.KnowledgeSessionOptions{
    APIURL:          "https://ingest.daguito.com",
    APIKey:          "sk_dgt_...",
    DefaultSourceID: "src_abc123",
})

_, err := kb.IngestText(ctx, daguito.IngestTextInput{
    Text:     "Daguito is a conversational AI platform...",
    Metadata: map[string]any{"workspace_id": "ws_42", "kind": "doc"},
})

topK := 5
result, err := kb.Search(ctx, daguito.SearchInput{Query: "what is daguito", TopK: &topK})
for _, h := range result.Hits {
    fmt.Println(h.Score, h.Content)
}

APIKey scopes (kb:read, kb:write) are configured in the dashboard.

Event reference

evt.Type Pointer field When
EventReady evt.Ready Socket authenticated
EventClosed evt.Closed Transport closed
EventNodeStarted evt.NodeStarted Engine entered a node
EventNodeToken evt.NodeToken LLM streaming token
EventNodeCompleted evt.NodeCompleted Node finished
EventNodeFailed evt.NodeFailed Node errored
EventNodeEmit evt.NodeEmit Tool progress / custom emits
EventFlowCompleted evt.FlowCompleted Engine finished
EventFlowFailed evt.FlowFailed Engine errored
EventError evt.Error Protocol-level error

Errors

The SDK exports sentinel errors so callers branch with errors.Is:

if errors.Is(err, daguito.ErrInvalidToken) { /* re-auth */ }
if errors.Is(err, daguito.ErrUploadFailed) { /* retry with backoff */ }

Sentinels: ErrInvalidToken, ErrWebhook, ErrUploadFailed, ErrKnowledge, ErrStream.

Examples

Runnable programs under examples/:

  • examples/run_webhook — one-shot HTTP call.
  • examples/stream_session — streaming session with a client-side tool.
DAGUITO_API_URL=https://ingest.daguito.com \
DAGUITO_WEBHOOK_ID=wh_abc123 \
DAGUITO_WEBHOOK_TOKEN=sk_wh_... \
go run ./examples/stream_session

Resources

License

MIT © Daguito, LLC

Documentation

Overview

Package daguito is the official Go SDK for the Daguito conversational AI platform — text, voice, image, audio, document and video agent flows.

It mirrors the public surface of the Python and TypeScript SDKs:

  • RunWebhook one-shot HTTP call to a flow.
  • WebhookStreamSession long-lived WebSocket; streams tokens and events.
  • UploadFile presigned upload for media attachments.
  • KnowledgeSession HTTP client for KB ingest + search.

Every public function that performs I/O takes a context.Context as its first argument and honours cancellation. The wire protocol (routes, frame types, base_input shape, scope filter, media envelope) is identical to the Python and JS SDKs — they are interchangeable from the server's point of view.

Index

Constants

View Source
const DefaultAPIURL = "https://ingest.daguito.com"

DefaultAPIURL is the Daguito ingest gateway — the default base URL for the SDK/inbound surface (webhooks, streaming, knowledge search, audio, upload). Callers may override it via ClientOptions.APIURL or the matching field on the standalone helper inputs.

Variables

View Source
var (
	// ErrInvalidToken is returned when a webhook or KB key is rejected.
	ErrInvalidToken = errors.New("daguito: invalid token")
	// ErrUploadFailed is returned when either the presign POST or the
	// follow-up PUT to object storage fails.
	ErrUploadFailed = errors.New("daguito: upload failed")
	// ErrKnowledge is returned for KB ingest/search failures.
	ErrKnowledge = errors.New("daguito: knowledge request failed")
	// ErrWebhook is returned when a one-shot webhook call fails (network or
	// non-2xx response).
	ErrWebhook = errors.New("daguito: webhook request failed")
	// ErrStream is returned for protocol-level streaming session errors.
	ErrStream = errors.New("daguito: stream session error")
)

Sentinel errors. Use errors.Is to branch on the well-known failure modes.

View Source
var ErrAdmin = errors.New("daguito: admin request failed")

ErrAdmin is the sentinel for admin-client failures (account keys, public flow keys, budgets). Use errors.Is to branch on it; errors.As against *httpError reveals the HTTP status + server message when available.

View Source
var ErrAudioStream = errors.New("audio stream")

ErrAudioStream is returned for any failure on the audio upstream channel.

View Source
var SupportedAudioCodecs = []string{"pcm16", "opus", "webm-opus", "mulaw", "flac"}

SupportedAudioCodecs mirrors the server's allowedCodecs set in apps/api/.../audio-ws.ts. Sending anything outside this list makes the server reject the socket on `open`.

View Source
var Version = "0.5.8"

Version is the SDK version exposed in X-Daguito-Client-Version headers. Override with -ldflags="-X github.com/daguitocontact-lang/go-sdk.Version=v0.3.1" at build time when releasing; the in-repo default tracks the latest tag.

Functions

func Int64Ptr added in v0.3.0

func Int64Ptr(v int64) *int64

Int64Ptr is a tiny convenience for callers building optional budget fields without having to declare a local variable first.

Types

type AccountKey added in v0.3.0

type AccountKey struct {
	ID                    string  `json:"id"`
	Name                  string  `json:"name"`
	KeyPrefix             string  `json:"key_prefix"`
	MonthlyBudgetMicroUsd *int64  `json:"monthly_budget_micro_usd"`
	CurrentMtdMicroUsd    int64   `json:"current_mtd_micro_usd"`
	CreatedAt             string  `json:"created_at"`
	LastUsedAt            *string `json:"last_used_at"`
	RevokedAt             *string `json:"revoked_at"`
}

AccountKey is the wire shape of a `dgsk_acc_…` org-wide credential.

JSON tags mirror the Python and JS SDKs exactly (key_prefix, monthly_budget_micro_usd, …) so admin payloads are interchangeable across the three SDKs.

type AccountKeyCreated added in v0.3.0

type AccountKeyCreated struct {
	AccountKey
	Plaintext string `json:"plaintext"`
}

AccountKeyCreated is the response of AccountKeys.Create. The Plaintext token is returned exactly once — persist it now or revoke and recreate.

type AccountKeysService added in v0.3.0

type AccountKeysService struct {
	// contains filtered or unexported fields
}

AccountKeysService manages `dgsk_acc_…` keys for the caller's org. Returned by Client.AccountKeys; never construct one yourself.

func (*AccountKeysService) Create added in v0.3.0

Create mints a new account key. The returned Plaintext is the only chance to capture the full token — store it, then discard the value.

func (*AccountKeysService) List added in v0.3.0

List returns every account key in the caller's org (active + revoked).

func (*AccountKeysService) Revoke added in v0.3.0

func (s *AccountKeysService) Revoke(ctx context.Context, keyID string) error

Revoke soft-deletes the key. Subsequent calls using it will fail auth. 204 No Content on success.

func (*AccountKeysService) SetBudget added in v0.3.0

func (s *AccountKeysService) SetBudget(
	ctx context.Context, keyID string, monthlyBudgetMicroUsd *int64,
) (*AccountKey, error)

SetBudget updates the per-key spending cap. Pass nil to clear the cap.

The PATCH /budget endpoint only echoes {id, monthly_budget_micro_usd}; the SDK re-fetches the canonical row via List so the caller still gets the full shape.

type AgentFlowResult added in v0.3.0

type AgentFlowResult struct {
	FlowID    string `json:"flow_id"`
	Slug      string `json:"slug"`
	Name      string `json:"name"`
	WebhookID string `json:"webhook_id"`
	Created   bool   `json:"created"`
}

AgentFlowResult is what the server returns from UpsertAgent.

type AgentFlowSpec added in v0.3.0

type AgentFlowSpec struct {
	Slug                string        `json:"slug"`
	Name                string        `json:"name"`
	Provider            string        `json:"provider"`
	Model               string        `json:"model"`
	SystemPrompt        string        `json:"system_prompt"`
	Temperature         *float64      `json:"temperature,omitempty"`
	MaxTokens           *int          `json:"max_tokens,omitempty"`
	HistoryTurns        *int          `json:"history_turns,omitempty"`
	RecentTurns         *int          `json:"recent_turns,omitempty"`
	MaxToolIterations   *int          `json:"max_tool_iterations,omitempty"`
	Tools               []FlowToolRef `json:"tools,omitempty"`
	MemoryFactsSchema   any           `json:"memory_facts_schema,omitempty"`
	MemorySummaryConfig any           `json:"memory_summary_config,omitempty"`
	ContextMemoryKeys   []string      `json:"context_memory_keys,omitempty"`
	// CoalesceEnabled, when set to false, disables the inbound coalesce
	// debounce + dedup for this flow. Use it when the caller's UI already
	// gates the composer client-side and a buffered turn would just add
	// latency. Defaults to true (coalesce on) when nil.
	CoalesceEnabled *bool `json:"coalesce_enabled,omitempty"`
}

AgentFlowSpec is the high-level declaration of a conversational agent flow. Each call to UpsertAgent uses Slug as the org-scoped identity: the first call creates the flow + webhook, subsequent calls update the agent config. The webhook id stays stable across upserts.

type AnalyticsService added in v0.5.2

type AnalyticsService struct {
	// contains filtered or unexported fields
}

AnalyticsService reads the caller's org usage snapshot from GET /v1/org/analytics. The org is resolved from the API key — there is no input.

func (*AnalyticsService) GetOrg added in v0.5.2

func (s *AnalyticsService) GetOrg(ctx context.Context) (*OrgAnalytics, error)

GetOrg returns the analytics snapshot for the caller's org.

type AudioStreamOptions added in v0.3.0

type AudioStreamOptions struct {
	APIURL string
	Token  string

	// SessionID ties this audio stream to a conversation. Pass the same
	// value to the companion WebhookStreamSession so the flow sees them
	// as one session_key. Empty → SDK mints a random one.
	SessionID string

	// Codec must be one of SupportedAudioCodecs. Defaults to "pcm16".
	Codec string

	// SampleRate is required when Codec == "pcm16" so the STT provider
	// knows the rate of the frames. Leave 0 for container codecs.
	SampleRate int

	// ReadyTimeout caps how long Connect blocks waiting for the server's
	// `ready` JSON frame. Default 10s.
	ReadyTimeout time.Duration
}

AudioStreamOptions configures an upstream-only audio session that pushes raw PCM (or other supported codec) chunks to Daguito's /v1/audio/:session_id WebSocket. Transcript / flow events arrive over the companion WebhookStreamSession on /v1/webhooks/:id/stream.

type AudioStreamReady added in v0.3.0

type AudioStreamReady struct {
	SessionKey string         `json:"session_key"`
	Codec      string         `json:"codec"`
	Guards     map[string]any `json:"guards,omitempty"`
}

AudioStreamReady carries the server-confirmed session metadata returned in the first JSON frame after a successful handshake.

type AudioStreamSession added in v0.3.0

type AudioStreamSession struct {
	// contains filtered or unexported fields
}

AudioStreamSession is a long-lived upstream audio channel.

Lifecycle:

s := NewAudioStreamSession(opts)
if err := s.Connect(ctx); err != nil { ... }
defer s.Close()
for chunk := range mic.Chunks() {
    if err := s.SendAudio(ctx, chunk); err != nil { ... }
}

SendAudio is safe to call from a single goroutine; concurrent senders must serialize themselves. Connect / Close are safe for concurrent use.

func NewAudioStreamSession added in v0.3.0

func NewAudioStreamSession(opts AudioStreamOptions) *AudioStreamSession

NewAudioStreamSession constructs a session. No I/O happens here — call Connect to open the socket.

func (*AudioStreamSession) Close added in v0.3.0

func (s *AudioStreamSession) Close() error

Close tears down the session. Server XADDs eof=1 to the audio Redis stream automatically on its end. Safe to call multiple times.

func (*AudioStreamSession) Connect added in v0.3.0

func (s *AudioStreamSession) Connect(ctx context.Context) error

Connect opens the WebSocket and blocks until the server's `ready` frame arrives (or ReadyTimeout fires).

func (*AudioStreamSession) Pause added in v0.5.8

func (s *AudioStreamSession) Pause(ctx context.Context) error

Pause closes the live STT segment (the provider stops billing) without ending the session. Resume reopens it on the next audio.

func (*AudioStreamSession) Ready added in v0.3.0

Ready returns the server-confirmed handshake metadata, or nil if the session is not yet open.

func (*AudioStreamSession) Resume added in v0.5.8

func (s *AudioStreamSession) Resume(ctx context.Context) error

Resume reopens the STT segment paused by Pause.

func (*AudioStreamSession) SendAudio added in v0.3.0

func (s *AudioStreamSession) SendAudio(ctx context.Context, chunk []byte) error

SendAudio pushes a single binary chunk. Caller decides chunk size — the server rejects frames over 256 KiB so 20–100 ms of audio per chunk is a reasonable target.

func (*AudioStreamSession) SendControl added in v0.5.8

func (s *AudioStreamSession) SendControl(ctx context.Context, control string) error

SendControl sends a text control frame on the audio socket. `pause` ends the live STT segment server-side — the transcription provider socket is closed so it stops billing — and `resume` opens a fresh segment, all WITHOUT tearing down the session. This lets a long consultation pause/resume on the same run instead of reconnecting (which would fragment the execution and re-bill the provider's connect time).

func (*AudioStreamSession) SessionID added in v0.3.0

func (s *AudioStreamSession) SessionID() string

SessionID returns the id used for this audio session. When opened with an empty SessionID, this is the random id the SDK minted — callers should read it back to use the same id on the companion event WS.

type BudgetsService added in v0.3.0

type BudgetsService struct {
	// contains filtered or unexported fields
}

BudgetsService manages the org-level monthly budget. Per-key budgets live on AccountKeysService.SetBudget / PublicKeysService.SetBudget.

func (*BudgetsService) GetOrg added in v0.3.0

func (s *BudgetsService) GetOrg(ctx context.Context) (*OrgBudget, error)

GetOrg returns the org-wide budget + MTD spend.

func (*BudgetsService) SetOrg added in v0.3.0

func (s *BudgetsService) SetOrg(
	ctx context.Context, monthlyBudgetMicroUsd *int64,
) (*OrgBudget, error)

SetOrg updates the org-wide monthly cap. Pass nil to clear it.

type Client added in v0.3.0

type Client struct {
	APIURL string
	APIKey string

	AccountKeys *AccountKeysService
	PublicKeys  *PublicKeysService
	Budgets     *BudgetsService
	Flows       *FlowsService
	Templates   *TemplatesService
	Models      *ModelsService
}

Client is the top-level admin client. It bundles the sub-services against the Daguito admin REST surface:

client.AccountKeys.List(ctx)
client.PublicKeys.Create(ctx, flowID, daguito.CreatePublicKeyInput{...})
client.Budgets.GetOrg(ctx)
client.Flows.UpsertAgent(ctx, daguito.AgentFlowSpec{...})

Auth uses a `dgsk_acc_…` account key (the dashboard session JWT is also accepted server-side). The existing top-level helpers — RunWebhook, WebhookStreamSession, KnowledgeSession, UploadFile — are unchanged; the Client is purely additive for management workflows.

func NewClient added in v0.3.0

func NewClient(opts ClientOptions) (*Client, error)

NewClient constructs a *Client. APIURL defaults to DefaultAPIURL (the ingest gateway) when empty. Returns an error if APIKey is empty — it is required and the typo is much easier to spot at the constructor than three calls later.

type ClientOptions added in v0.3.0

type ClientOptions struct {
	// APIURL is the Daguito ingest gateway root. When empty, NewClient falls
	// back to DefaultAPIURL.
	APIURL string
	APIKey string
	// HTTPClient is an optional override. When nil, NewClient uses
	// http.DefaultClient.
	HTTPClient *http.Client
}

ClientOptions configures NewClient.

type ClosedEvent

type ClosedEvent struct {
	Code   int
	Reason string
}

ClosedEvent fires when the transport closes. Code/Reason are best-effort — some closures (peer drop, network) leave them empty.

type CreateAccountKeyInput added in v0.3.0

type CreateAccountKeyInput struct {
	Name                  string `json:"name"`
	MonthlyBudgetMicroUsd *int64 `json:"monthly_budget_micro_usd,omitempty"`
}

CreateAccountKeyInput is the request body for AccountKeys.Create.

Pass a pointer for MonthlyBudgetMicroUsd so callers can distinguish "no cap" (nil) from "explicit zero" — the wire shape needs the same distinction.

type CreateKnowledgeSourceInput added in v0.5.2

type CreateKnowledgeSourceInput struct {
	OrgID       string `json:"org_id"`
	Name        string `json:"name"`
	Description string `json:"description,omitempty"`
	Kind        string `json:"kind,omitempty"`
}

CreateKnowledgeSourceInput is the request body for CreateSource. Kind is one of "url", "file", "text", "sitemap"; the server defaults to "text" when empty.

type CreatePublicKeyInput added in v0.3.0

type CreatePublicKeyInput struct {
	Name                  string   `json:"name"`
	AllowedOrigins        []string `json:"allowed_origins"`
	MonthlyBudgetMicroUsd *int64   `json:"monthly_budget_micro_usd,omitempty"`
}

CreatePublicKeyInput is the request body for PublicKeys.Create.

type DeleteChunksByMetadataInput added in v0.5.2

type DeleteChunksByMetadataInput struct {
	MetadataKey   string
	MetadataValue string
}

DeleteChunksByMetadataInput targets every chunk in a source whose metadata key equals the given value. Idempotent — DeletedCount=0 when nothing matches.

type DeleteChunksByMetadataResult added in v0.5.2

type DeleteChunksByMetadataResult struct {
	DeletedCount int `json:"deleted_count"`
}

DeleteChunksByMetadataResult is the response of DeleteChunksByMetadata.

type ErrorEvent

type ErrorEvent struct {
	Message string
}

ErrorEvent carries a protocol-level error (auth failure, malformed frame, etc.). It is not the same as NodeFailedEvent / FlowFailedEvent — those are flow-execution failures.

type EventType

type EventType string

EventType is the wire-level event name for a StreamEvent. Mirrors the Python `StreamEvent` literal union.

const (
	EventReady         EventType = "ready"
	EventClosed        EventType = "closed"
	EventNodeStarted   EventType = "node.started"
	EventNodeToken     EventType = "node.token"
	EventNodeCompleted EventType = "node.completed"
	EventNodeFailed    EventType = "node.failed"
	EventNodeEmit      EventType = "node.emit"
	EventFlowCompleted EventType = "flow.completed"
	EventFlowFailed    EventType = "flow.failed"
	EventError         EventType = "error"
)

type FlowCompletedEvent

type FlowCompletedEvent struct {
	ElapsedMs int
	Output    any
}

FlowCompletedEvent fires when the engine finishes the run. ElapsedMs is measured client-side from session.started.

type FlowFailedEvent

type FlowFailedEvent struct {
	Error string
}

FlowFailedEvent fires when the engine errors out.

type FlowGraph added in v0.4.1

type FlowGraph struct {
	Nodes []FlowGraphNode `json:"nodes"`
	Edges []FlowGraphEdge `json:"edges"`
	// CoalesceEnabled, when set to false, disables the inbound coalesce
	// debounce + dedup for this flow — same flag as AgentFlowSpec, but for
	// custom graphs. Declared here so a graph JSON can carry it inline.
	// Nodes may omit `position`; the server auto-lays-out any that do, so a
	// minimal graph is just nodes + edges. Defaults to true when nil.
	CoalesceEnabled *bool `json:"coalesce_enabled,omitempty"`
}

FlowGraph is a complete node/edge graph for a custom flow.

type FlowGraphEdge added in v0.4.1

type FlowGraphEdge struct {
	ID           string `json:"id"`
	Source       string `json:"source"`
	Target       string `json:"target"`
	SourceHandle string `json:"sourceHandle,omitempty"`
}

FlowGraphEdge wires one node's output to another node's input.

type FlowGraphNode added in v0.4.1

type FlowGraphNode struct {
	ID       string         `json:"id"`
	Type     string         `json:"type,omitempty"`
	Kind     string         `json:"kind,omitempty"`
	Config   map[string]any `json:"config,omitempty"`
	Position *FlowNodePos   `json:"position,omitempty"`
}

FlowGraphNode is one node of a custom flow graph. `Config` carries the node's `step_type` plus every step-specific field — its shape depends on the step type, so it stays a free-form map.

type FlowNodePos added in v0.4.1

type FlowNodePos struct {
	X float64 `json:"x"`
	Y float64 `json:"y"`
}

FlowNodePos is the editor canvas position of a node (cosmetic).

type FlowResult added in v0.4.1

type FlowResult struct {
	FlowID    string `json:"flow_id"`
	Slug      string `json:"slug"`
	Name      string `json:"name"`
	WebhookID string `json:"webhook_id"`
	Created   bool   `json:"created"`
}

FlowResult is what the server returns from UpsertFlow.

type FlowSpec added in v0.4.1

type FlowSpec struct {
	Slug string `json:"slug"`
	Name string `json:"name"`
	// TriggerType for the flow row; defaults to "message" server-side when
	// empty. Streaming consultations use "message".
	TriggerType string    `json:"trigger_type,omitempty"`
	Graph       FlowGraph `json:"graph"`
}

FlowSpec declares a flow as a full custom graph. Unlike AgentFlowSpec (the `trigger → ai_agent` preset), this carries any node/edge graph — STT pipelines, extraction chains, multi-branch flows. Identity is (org_id, slug); the org comes from the client's API key.

type FlowToolRef added in v0.3.0

type FlowToolRef struct {
	Kind         string         `json:"kind"`
	Name         string         `json:"name"`
	Config       map[string]any `json:"config,omitempty"`
	RequiresData *RequiresData  `json:"requires_data,omitempty"`
}

FlowToolRef declares a single tool the agent can call. Today only the `handler` kind (server-side registered tools like `search_knowledge`, `web_search`) is supported via this endpoint.

type FlowsService added in v0.3.0

type FlowsService struct {
	// contains filtered or unexported fields
}

FlowsService administers flow definitions on Daguito. Today exposes the "agent" preset (system_prompt + tools + model + memory + a trigger → agent graph built server-side). Full flow CRUD with custom graphs is Phase 3.

func (*FlowsService) ResolveWebhook added in v0.4.0

func (s *FlowsService) ResolveWebhook(
	ctx context.Context, slug string,
) (*ResolvedFlowWebhook, error)

ResolveWebhook resolves a flow by slug (in the org the API key belongs to) and returns its streaming webhook id + a usable sk_wh_… token, so a client can open an AudioStream / WebhookStream session without hardcoding webhook credentials. The token is reused when the flow already has one.

func (*FlowsService) UpsertAgent added in v0.3.0

func (s *FlowsService) UpsertAgent(
	ctx context.Context, spec AgentFlowSpec,
) (*AgentFlowResult, error)

UpsertAgent creates a new agent flow on first call, updates it on subsequent calls. Identity is (org_id, slug). The org is resolved from the client's API key. Returns the canonical flow/webhook ids — store WebhookID and pass it to NewWebhookStreamSession.

func (*FlowsService) UpsertFlow added in v0.4.1

func (s *FlowsService) UpsertFlow(
	ctx context.Context, spec FlowSpec,
) (*FlowResult, error)

UpsertFlow creates a flow from a full custom graph on first call and updates it on subsequent calls, idempotent by (org_id, slug). Use it for flows that are not the agent preset — STT + extraction pipelines, etc. The webhook id stays stable across upserts.

type IngestJob added in v0.5.2

type IngestJob struct {
	JobID  string         `json:"job_id"`
	Status string         `json:"status"`
	OrgID  string         `json:"org_id,omitempty"`
	Raw    map[string]any `json:"-"`
}

IngestJob is the response of IngestURL / IngestText admin calls plus GetIngestJob. The shape mirrors the server's ingest-queue snapshot; extra fields (`progress`, `result`, …) ride through as Raw.

func (*IngestJob) UnmarshalJSON added in v0.5.2

func (j *IngestJob) UnmarshalJSON(data []byte) error

UnmarshalJSON keeps the canonical fields typed and stuffs the rest into Raw, so callers can read provider-specific extras without losing them to a static struct.

type IngestTextAdminInput added in v0.5.2

type IngestTextAdminInput struct {
	Text     string         `json:"text"`
	Metadata map[string]any `json:"metadata,omitempty"`
}

IngestTextAdminInput is the request body for IngestText on the admin surface. Identical shape to KnowledgeSession.IngestText but routed through `/api/public/knowledge/sources/:id/text`.

type IngestTextInput

type IngestTextInput struct {
	Text     string
	Metadata map[string]any
	SourceID string // overrides DefaultSourceID when set
}

IngestTextInput is the input to KnowledgeSession.IngestText.

type IngestTextResult

type IngestTextResult struct {
	SourceID   string
	ChunkCount int
	TokenCount int
}

IngestTextResult is the response of a successful text-ingest.

type IngestURLInput added in v0.5.2

type IngestURLInput struct {
	URL      string         `json:"url"`
	Metadata map[string]any `json:"metadata,omitempty"`
}

IngestURLInput is the request body for IngestURL.

type KnowledgeBase added in v0.5.2

type KnowledgeBase struct {
	ID                string  `json:"id"`
	Name              string  `json:"name"`
	Description       *string `json:"description"`
	Dim               int     `json:"dim"`
	TenancyTier       string  `json:"tenancy_tier"`
	EmbeddingProvider string  `json:"embedding_provider"`
	EmbeddingModel    string  `json:"embedding_model"`
}

KnowledgeBase is the wire shape of a knowledge_bases row returned by GET /api/public/knowledge/bases.

type KnowledgeService added in v0.5.2

type KnowledgeService struct {
	// contains filtered or unexported fields
}

KnowledgeService is the management surface for knowledge bases and sources. It uses the `dgsk_acc_…` / `sk_dgt_…` account credential bound to the org — every call resolves the org server-side.

The data-plane KB session (text ingest + search via a per-source `sk_dgt_…` key) lives separately in KnowledgeSession; both can be used independently or together.

func (*KnowledgeService) CreateSource added in v0.5.2

CreateSource provisions a new KB + default source in one call.

func (*KnowledgeService) DeleteChunksByMetadata added in v0.5.2

func (s *KnowledgeService) DeleteChunksByMetadata(
	ctx context.Context, sourceID string, in DeleteChunksByMetadataInput,
) (*DeleteChunksByMetadataResult, error)

DeleteChunksByMetadata deletes every chunk in `sourceID` whose metadata key/value matches `in`. Returns 0 + nil error when nothing matches (idempotent).

func (*KnowledgeService) DeleteSource added in v0.5.2

func (s *KnowledgeService) DeleteSource(ctx context.Context, sourceID string) error

DeleteSource permanently removes the source row + its vectors.

func (*KnowledgeService) GetIngestJob added in v0.5.2

func (s *KnowledgeService) GetIngestJob(
	ctx context.Context, jobID string,
) (*IngestJob, error)

GetIngestJob fetches the status of an asynchronous ingest job.

func (*KnowledgeService) IngestText added in v0.5.2

func (s *KnowledgeService) IngestText(
	ctx context.Context, sourceID string, in IngestTextAdminInput,
) (*IngestJob, error)

IngestText kicks off a text ingest against the given source. The data-plane KB session has its own IngestText for the per-source key flow; this one uses the org account credential.

func (*KnowledgeService) IngestURL added in v0.5.2

func (s *KnowledgeService) IngestURL(
	ctx context.Context, sourceID string, in IngestURLInput,
) (*IngestJob, error)

IngestURL kicks off an asynchronous URL ingest against the given source. Poll the returned IngestJob via GetIngestJob until Status == "ready".

func (*KnowledgeService) ListBases added in v0.5.2

func (s *KnowledgeService) ListBases(
	ctx context.Context, opts ListKnowledgeOptions,
) ([]KnowledgeBase, error)

ListBases lists every knowledge base owned by the org. OrgID is optional — when omitted, the server falls back to the org the API key belongs to (account keys live in exactly one org).

func (*KnowledgeService) ListSources added in v0.5.2

func (s *KnowledgeService) ListSources(
	ctx context.Context, opts ListKnowledgeOptions,
) ([]KnowledgeSource, error)

ListSources lists the org's knowledge sources, already rolled up to one entry per knowledge base by the server. OrgID is optional — when omitted, the server falls back to the org the API key belongs to.

func (*KnowledgeService) UpdateChunksMetadata added in v0.5.2

func (s *KnowledgeService) UpdateChunksMetadata(
	ctx context.Context, sourceID string, in UpdateChunksMetadataInput,
) (*UpdateChunksMetadataResult, error)

UpdateChunksMetadata patches metadata of every chunk in `sourceID` matching `in.Match`. The wire body uses snake_case keys (`metadata_key`, `metadata_value`); this method translates from the CamelCase Go input.

type KnowledgeSession

type KnowledgeSession struct {
	// contains filtered or unexported fields
}

KnowledgeSession is an HTTP client for the Daguito KB ingest + search endpoints. It is safe to reuse across goroutines.

func NewKnowledgeSession

func NewKnowledgeSession(opts KnowledgeSessionOptions) *KnowledgeSession

NewKnowledgeSession constructs a KB client. No I/O happens here.

func (*KnowledgeSession) IngestText

IngestText ingests a text blob into the configured source. The server chunks, embeds, and indexes the text. Returns the chunk + token counts so the caller can audit cost.

func (*KnowledgeSession) Search

Search runs a hybrid (BM25 + vector) search against the KB.

type KnowledgeSessionOptions

type KnowledgeSessionOptions struct {
	APIURL          string
	APIKey          string // sk_dgt_... — kb:read / kb:write scoped key
	DefaultSourceID string // optional default sourceId for IngestText
	Timeout         time.Duration
	HTTPClient      *http.Client
}

KnowledgeSessionOptions configures a KnowledgeSession.

type KnowledgeSource added in v0.5.2

type KnowledgeSource struct {
	ID          string  `json:"id"`
	OrgID       string  `json:"org_id"`
	KbID        string  `json:"kb_id"`
	Name        string  `json:"name"`
	Description *string `json:"description"`
	Kind        string  `json:"kind"`
	Status      string  `json:"status"`
	ChunkCount  int     `json:"chunk_count"`
	TokenCount  int     `json:"token_count"`
	SourceCount int     `json:"source_count,omitempty"`
	CreatedAt   string  `json:"created_at"`
	UpdatedAt   string  `json:"updated_at"`
}

KnowledgeSource is the rolled-up "one card per kb" shape the dashboard endpoint returns. ID is the latest underlying source row id; SourceCount reveals how many raw sources were merged.

type ListKnowledgeOptions added in v0.5.2

type ListKnowledgeOptions struct {
	OrgID string
}

ListKnowledgeOptions is the input to ListBases / ListSources. OrgID is required — the server enforces it against the calling key.

type MediaKind

type MediaKind string

MediaKind enumerates the message kinds that carry an uploaded attachment. The values match the canonical MessageKind enum in @daguito/core (packages/core/src/messages/kinds.ts).

const (
	MediaKindImage    MediaKind = "image"
	MediaKindAudio    MediaKind = "audio"
	MediaKindDocument MediaKind = "document"
	MediaKindVideo    MediaKind = "video"
)

type Model added in v0.5.2

type Model struct {
	Provider    string `json:"provider"`
	ID          string `json:"model_id"`
	DisplayName string `json:"display_name"`
	Tier        string `json:"tier,omitempty"`
}

Model is one curated LLM entry. ID is the `<provider>/<model>` string that flow node configs expect (e.g. `google/gemini-3.5-flash`). DisplayName + Tier are UI hints — Tier is the free-form bucket the dashboard surfaces ("fast", "balanced", "smart"), empty when the operator hasn't tagged it.

type ModelsService added in v0.5.2

type ModelsService struct {
	// contains filtered or unexported fields
}

ModelsService wraps the `/v1/models` endpoint. The endpoint returns the curated LLM picker list — the same rows the dashboard's flow builder shows — so SDK / MCP integrations can render a model selector and pass the chosen id into flow node configs (e.g. `ai_agent.model`, pre-recorded / realtime LLM nodes inside graph flows).

Auth is the same `dgsk_acc_…` bearer key used by the other admin services — the list is scoped to the caller's org.

func (*ModelsService) List added in v0.5.2

func (s *ModelsService) List(ctx context.Context) ([]Model, error)

List returns the curated LLM models available to the caller's org.

type NodeCatalog added in v0.5.2

type NodeCatalog = map[string]any

NodeCatalog is the raw catalog the server returns. Its shape evolves frequently (new node kinds, new descriptors), so the SDK keeps it as a pass-through map — callers index by `step_type` and read whatever fields they need without coupling to a frozen Go struct.

type NodeCompletedEvent

type NodeCompletedEvent struct {
	NodeID     string
	DurationMs int
	Output     any
}

NodeCompletedEvent fires when a node finishes successfully. DurationMs is populated when the server reports it; Output may be any JSON-shaped value.

type NodeEmitEvent

type NodeEmitEvent struct {
	NodeID string
	Kind   string
	Data   map[string]any
}

NodeEmitEvent carries custom telemetry. Kind discriminates the payload; common values: "tool_progress" (use ParseToolProgress), "intent", "agent.tool_call_started".

type NodeFailedEvent

type NodeFailedEvent struct {
	NodeID string
	Error  string
}

NodeFailedEvent fires when a node errors out.

type NodeStartedEvent

type NodeStartedEvent struct {
	NodeID string
}

NodeStartedEvent fires when the engine enters a flow node.

type NodeTokenEvent

type NodeTokenEvent struct {
	NodeID string
	Text   string
}

NodeTokenEvent carries a single LLM token (or the smallest unit the model streamed). Concatenate Text across consecutive events to reconstruct the full response.

type NodesService added in v0.5.2

type NodesService struct {
	// contains filtered or unexported fields
}

NodesService reads the flow-builder node catalog. Backed by GET /api/public/nodes/catalog — no auth required, but the SDK still sends the bearer to match the rest of the surface.

func (*NodesService) GetCatalog added in v0.5.2

func (s *NodesService) GetCatalog(ctx context.Context) (NodeCatalog, error)

GetCatalog returns the full node catalog as a generic map.

type OrgAnalytics added in v0.5.2

type OrgAnalytics struct {
	OrgID         string            `json:"org_id"`
	LLMToday      OrgLLMUsage       `json:"llm_today"`
	MessagesToday OrgMessagesUsage  `json:"messages_today"`
	HTTPToday     OrgHTTPUsage      `json:"http_today"`
	Budget        OrgBudgetSnapshot `json:"budget"`
}

OrgAnalytics is the wire shape of GET /v1/org/analytics.

type OrgBudget added in v0.3.0

type OrgBudget struct {
	MonthlyBudgetMicroUsd *int64  `json:"monthly_budget_micro_usd"`
	CurrentMtdMicroUsd    int64   `json:"current_mtd_micro_usd"`
	MtdResetAt            *string `json:"mtd_reset_at"`
}

OrgBudget is the org-level spending state returned by Budgets.GetOrg.

type OrgBudgetSnapshot added in v0.5.2

type OrgBudgetSnapshot struct {
	OrgCapMicroUsd *int64 `json:"org_cap_micro_usd"`
	OrgMtdMicroUsd int64  `json:"org_mtd_micro_usd"`
	KeyCapMicroUsd *int64 `json:"key_cap_micro_usd"`
	KeyMtdMicroUsd int64  `json:"key_mtd_micro_usd"`
}

OrgBudgetSnapshot is the budget portion of OrgAnalytics. Caps are micro-USD (1e-6 USD) — same unit as the Budgets surface. Cap fields are pointers because the server returns JSON `null` when the cap is unset.

type OrgHTTPUsage added in v0.5.2

type OrgHTTPUsage struct {
	Total  int            `json:"total"`
	ByPath map[string]int `json:"by_path"`
}

OrgHTTPUsage is the HTTP request volume for the org over the current day.

type OrgLLMUsage added in v0.5.2

type OrgLLMUsage struct {
	Requests int     `json:"requests"`
	Tokens   int     `json:"tokens"`
	CostUSD  float64 `json:"cost_usd"`
}

OrgLLMUsage is today's LLM activity for the caller's org.

type OrgMessagesUsage added in v0.5.2

type OrgMessagesUsage struct {
	Inbound         map[string]int `json:"inbound"`
	OutboundLast24h int            `json:"outbound_last_24h"`
}

OrgMessagesUsage is the message volume snapshot returned by GetOrg. Inbound is keyed by channel (whatsapp, widget, instagram, …) — the SDK keeps it as a map so new channels show up without a code change.

type PublicKey added in v0.3.0

type PublicKey struct {
	ID                    string   `json:"id"`
	FlowID                string   `json:"flow_id"`
	Name                  string   `json:"name"`
	KeyPrefix             string   `json:"key_prefix"`
	AllowedOrigins        []string `json:"allowed_origins"`
	MonthlyBudgetMicroUsd *int64   `json:"monthly_budget_micro_usd"`
	CurrentMtdMicroUsd    int64    `json:"current_mtd_micro_usd"`
	CreatedAt             string   `json:"created_at"`
	LastUsedAt            *string  `json:"last_used_at"`
	RevokedAt             *string  `json:"revoked_at"`
}

PublicKey is the wire shape of a `dgpk_flow_…` browser-safe credential bound to a single flow + an allowed-origins allowlist.

type PublicKeyCreated added in v0.3.0

type PublicKeyCreated struct {
	PublicKey
	Plaintext string `json:"plaintext"`
}

PublicKeyCreated is the response of PublicKeys.Create.

type PublicKeysService added in v0.3.0

type PublicKeysService struct {
	// contains filtered or unexported fields
}

PublicKeysService manages `dgpk_flow_…` browser-safe keys per flow. Returned by Client.PublicKeys.

func (*PublicKeysService) Create added in v0.3.0

Create mints a CORS-locked browser key. AllowedOrigins must contain at least one entry — the server enforces the allowlist on every request.

func (*PublicKeysService) List added in v0.3.0

func (s *PublicKeysService) List(ctx context.Context, flowID string) ([]PublicKey, error)

List returns every public flow key for the given flow.

func (*PublicKeysService) Revoke added in v0.3.0

func (s *PublicKeysService) Revoke(ctx context.Context, flowID, keyID string) error

Revoke soft-deletes the key.

func (*PublicKeysService) SetBudget added in v0.3.0

func (s *PublicKeysService) SetBudget(
	ctx context.Context, flowID, keyID string, monthlyBudgetMicroUsd *int64,
) (*PublicKey, error)

SetBudget updates the per-key spending cap. Pass nil to clear it.

type ReadyEvent

type ReadyEvent struct {
	WebhookID string
}

ReadyEvent fires after the WS upgrade and bearer-token auth succeed.

type RequiresData added in v0.5.2

type RequiresData struct {
	// KBScope = true: hide unless the session's KB scope has any chunks.
	// Used by `search_knowledge` so the LLM doesn't call it before any
	// document has been indexed for the scope.
	KBScope bool `json:"kb_scope,omitempty"`
}

RequiresData gates a tool from the LLM until the named data is available on the session. Daguito hides the tool from the model when the gate is unmet, so the prompt stays clean of dead-end calls.

type ResolvedFlowWebhook added in v0.4.0

type ResolvedFlowWebhook struct {
	FlowID       string `json:"flow_id"`
	Slug         string `json:"slug"`
	Name         string `json:"name"`
	WebhookID    string `json:"webhook_id"`
	WebhookToken string `json:"webhook_token"`
}

ResolvedFlowWebhook is the streaming webhook a flow resolves to.

type SearchHit

type SearchHit struct {
	ID       string
	SourceID string
	Content  string
	Score    float64
	Metadata map[string]any
}

SearchHit is a single chunk returned by the KB search.

type SearchInput

type SearchInput struct {
	Query         string
	TopK          *int
	SourceIDs     []string
	EnableRewrite *bool
	EnableRerank  *bool
	EnableCache   *bool
}

SearchInput is the input to KnowledgeSession.Search. Set pointers via the helper constructors below — the SDK omits nil pointers from the wire body so server defaults apply.

type SearchResult

type SearchResult struct {
	Hits           []SearchHit
	QueryOriginal  string
	QueryRewritten string
	Raw            map[string]any
}

SearchResult is the response of a KB search.

type SendableMessage

type SendableMessage struct {
	Kind string `json:"kind"`
	Text string `json:"text,omitempty"`

	ImageURL  string   `json:"image_url,omitempty"`
	ImageURLs []string `json:"image_urls,omitempty"`

	MediaKey string `json:"media_key,omitempty"`
	// MediaURL is a short-lived presigned GET the integrator hosts in ITS OWN
	// storage. When set, Daguito fetches the bytes from here instead of signing
	// MediaKey against its own storage (client-owned media; see MediaRefSchema.url
	// in @daguito/core). MediaKey stays the stable identity that keys the
	// description cache / cross-turn memory.
	MediaURL  string `json:"media_url,omitempty"`
	MimeType  string `json:"mime_type,omitempty"`
	SizeBytes int64  `json:"size_bytes,omitempty"`

	FormID  string         `json:"form_id,omitempty"`
	Payload map[string]any `json:"payload,omitempty"`
}

SendableMessage is the wire shape accepted by WebhookStreamSession.Send. In TypeScript this is a discriminated union; in Go we model it as a struct with optional fields and a Kind tag. Use the helper constructors below — they fill the correct subset of fields for each kind. The session wraps MediaKey/MimeType/SizeBytes into the nested `media` object Daguito expects inside `toInbound`.

Wire kinds:

  • "text"
  • "image" with ImageURL or MediaKey (pre-uploaded)
  • "image-multi" with ImageURLs
  • "audio" / "document" / "video" with MediaKey
  • "form-response" with FormID + Payload

func FormResponseMessage

func FormResponseMessage(formID string, payload map[string]any) SendableMessage

FormResponseMessage resumes a flow that paused on a form node.

func ImageMultiMessage

func ImageMultiMessage(imageURLs []string, text string) SendableMessage

ImageMultiMessage attaches several public image URLs for comparison / multi-image prompts.

func ImageURLMessage

func ImageURLMessage(imageURL, text string) SendableMessage

ImageURLMessage attaches a single public image URL. The flow's vision tool fetches it server-side — no upload happens here.

func MediaKeyMessage

func MediaKeyMessage(kind MediaKind, mediaKey, mimeType string, sizeBytes int64, text string) SendableMessage

MediaKeyMessage attaches a previously uploaded media object identified by the key returned from UploadFile. kind is one of MediaKindImage, MediaKindAudio, MediaKindDocument, MediaKindVideo.

func MediaURLMessage added in v0.5.6

func MediaURLMessage(kind MediaKind, key, mediaURL, mimeType string, sizeBytes int64, text string) SendableMessage

MediaURLMessage attaches client-owned media: the bytes live in the integrator's OWN storage and mediaURL is a short-lived presigned GET that Daguito fetches from, instead of mirroring the bytes into Daguito storage first. key stays the stable identity (path/id, NOT a URL) that keys the description cache so cross-turn memory works by reference. kind is one of MediaKindAudio, MediaKindDocument, MediaKindVideo, MediaKindImage.

func TextMessage

func TextMessage(text string) SendableMessage

TextMessage builds a plain text message.

type StreamEvent

type StreamEvent struct {
	Type EventType

	Ready         *ReadyEvent
	Closed        *ClosedEvent
	NodeStarted   *NodeStartedEvent
	NodeToken     *NodeTokenEvent
	NodeCompleted *NodeCompletedEvent
	NodeFailed    *NodeFailedEvent
	NodeEmit      *NodeEmitEvent
	FlowCompleted *FlowCompletedEvent
	FlowFailed    *FlowFailedEvent
	Error         *ErrorEvent
}

StreamEvent is the sum type delivered on WebhookStreamSession.Events(). The Type field selects which of the typed payload pointers is populated; at most one is non-nil. Switch on Type when handling, or use the helper accessor methods.

type TemplateFieldDetail added in v0.4.3

type TemplateFieldDetail struct {
	Name        string   `json:"name"`
	Description string   `json:"description"`
	Type        string   `json:"type"`
	EnumValues  []string `json:"enum_values,omitempty"`
}

TemplateFieldDetail describes a single placeholder in the template, with the inferred type and (for enum fields) the candidate values.

type TemplatePreviewExample added in v0.4.3

type TemplatePreviewExample struct {
	Transcript       string         `json:"transcript"`
	TranscriptOrigin string         `json:"transcript_origin"`
	Extracted        map[string]any `json:"extracted"`
	Model            string         `json:"model"`
}

TemplatePreviewExample is the model-extracted example payload the server returns when an example transcript is available. Extracted is a free-form map keyed by placeholder name — its values come from the LLM and reflect the inferred schema.

type TemplatePreviewInput added in v0.4.3

type TemplatePreviewInput struct {
	TemplateBody    string `json:"template_body"`
	Vertical        string `json:"vertical,omitempty"`
	Model           string `json:"model,omitempty"`
	ForceRegenerate bool   `json:"force_regenerate,omitempty"`
}

TemplatePreviewInput is the request body for Preview. TemplateBody is required; every other field is optional.

type TemplatePreviewResult added in v0.4.3

type TemplatePreviewResult struct {
	TemplateSchema TemplateSchema           `json:"template_schema"`
	FieldNames     []string                 `json:"field_names"`
	FieldCount     int                      `json:"field_count"`
	FieldsDetail   []TemplateFieldDetail    `json:"fields_detail"`
	Example        *TemplatePreviewExample  `json:"example"`
	Warnings       []TemplatePreviewWarning `json:"warnings"`
	BodyHash       string                   `json:"body_hash"`
}

TemplatePreviewResult is what the server returns from POST /v1/templates/preview. Example is nil when the API did not run the extractor (e.g. no transcript supplied + Generate disabled). BodyHash is a stable digest of the input template body — callers can use it as a cache key for downstream LLM prompts.

type TemplatePreviewWarning added in v0.4.3

type TemplatePreviewWarning struct {
	Code    string `json:"code"`
	Field   string `json:"field,omitempty"`
	Message string `json:"message"`
	Hint    string `json:"hint,omitempty"`
}

TemplatePreviewWarning is a non-fatal hint emitted by the parser (placeholder with no body, duplicate name, etc).

type TemplateSchema added in v0.4.3

type TemplateSchema struct {
	Name   string         `json:"name"`
	Schema map[string]any `json:"schema"`
}

TemplateSchema is the JSON schema inferred from the template body. Schema mirrors the JSON Schema object the API returns — kept as a generic map because callers compose it into LLM tool definitions.

type TemplatesService added in v0.4.3

type TemplatesService struct {
	// contains filtered or unexported fields
}

TemplatesService wraps the `/v1/templates/preview` endpoint. The endpoint inspects a template body that uses `[[natural-language description]]` placeholders, infers a JSON schema for it, and (when the server decides to run the extractor) asks the model to extract a sample payload. The placeholder body is plain description — there is no `| type` syntax, the model infers the field type downstream.

Auth is the same `dgsk_acc_…` bearer key used by FlowsService — templates run in the org bound to the account key.

func (*TemplatesService) Preview added in v0.4.3

Preview wraps POST /v1/templates/preview. TemplateBody is required; returns the inferred schema, the typed field list, optional warnings, the body hash, and (when the API ran the extractor) an example payload.

type ToolHandler

type ToolHandler func(ctx context.Context, args json.RawMessage) (any, error)

ToolHandler runs locally when the agent invokes a registered tool. Return any JSON-serialisable value as the tool result. Return an error to surface a failure to the LLM.

type ToolProgressEvent

type ToolProgressEvent struct {
	Tool     string
	Stage    string
	Progress float64 // 0..1; -1 when not reported
	Resource *ToolProgressResource
	Result   *ToolProgressResult
	TraceID  string
	Attempt  int
}

ToolProgressEvent is the typed view over a NodeEmitEvent whose Kind is "tool_progress". Returned by ParseToolProgress. Consumers compose the user-facing copy from (Tool, Stage, Resource, Result) via their own i18n layer — the SDK never localises strings.

func ParseToolProgress

func ParseToolProgress(evt *NodeEmitEvent) *ToolProgressEvent

ParseToolProgress narrows a NodeEmitEvent into a ToolProgressEvent when Kind is "tool_progress". Returns nil otherwise so callers can use it as a discriminator inside their node.emit handler.

type ToolProgressItem

type ToolProgressItem struct {
	Title   string
	Snippet string
	URL     string
}

ToolProgressItem is one hit in a search-like tool result.

type ToolProgressResource

type ToolProgressResource struct {
	Kind     string
	Name     string
	MediaKey string
	URL      string
}

ToolProgressResource describes what a tool is operating on. Every field is optional — the server only fills what's relevant for the stage.

type ToolProgressResult

type ToolProgressResult struct {
	Summary string
	Items   []ToolProgressItem
}

ToolProgressResult carries the data the tool produced. Summary is the raw caption/transcript text for a single-resource tool; Items lists multiple hits for search-like tools.

type ToolSpec

type ToolSpec struct {
	Name        string         `json:"name"`
	Description string         `json:"description"`
	Parameters  map[string]any `json:"parameters"`
	// TimeoutMS caps how long the SDK waits for the local handler before
	// reporting a tool error back to the LLM. Defaults to 30s.
	TimeoutMS int `json:"client_timeout_ms,omitempty"`
}

ToolSpec is the OpenAI-shaped declaration the LLM sees. Parameters is a JSON Schema fragment (typically `{"type":"object","properties":{...}}`).

type UpdateChunksMetadataInput added in v0.5.2

type UpdateChunksMetadataInput struct {
	Match UpdateChunksMetadataMatch
	Patch map[string]any
}

UpdateChunksMetadataInput patches every chunk in a source that matches Match. Patch keys overwrite, others are preserved (shallow merge).

type UpdateChunksMetadataMatch added in v0.5.2

type UpdateChunksMetadataMatch struct {
	MetadataKey   string
	MetadataValue string
}

UpdateChunksMetadataMatch is the matcher passed to UpdateChunksMetadata.

type UpdateChunksMetadataResult added in v0.5.2

type UpdateChunksMetadataResult struct {
	UpdatedCount int `json:"updated_count"`
}

UpdateChunksMetadataResult is the response of UpdateChunksMetadata.

type UploadInput

type UploadInput struct {
	APIURL    string
	WebhookID string
	Token     string
	Kind      MediaKind
	Path      string
	Data      []byte
	Filename  string
	MimeType  string
	Timeout   time.Duration // optional; defaults to 30s
	// HTTPClient is an optional override. When nil, UploadFile uses
	// http.DefaultClient.
	HTTPClient *http.Client
}

UploadInput is the input to UploadFile. Exactly one of Path or Data must be set. When Data is provided, Filename is required (used for both the extension-based MIME fallback and the storage key suffix).

type UploadResult

type UploadResult struct {
	MediaKey     string
	MimeType     string
	SizeBytes    int64
	ExpiresInSec int
}

UploadResult is the output of a successful presign + PUT.

func UploadFile

func UploadFile(ctx context.Context, input UploadInput) (*UploadResult, error)

UploadFile uploads a local file (or in-memory bytes) to Daguito object storage and returns the media_key. Hand the key to MediaKeyMessage on a subsequent WebhookStreamSession.Send.

The upload is a two-step dance: (1) POST /v1/webhooks/:id/upload to mint a presigned PUT URL, (2) PUT bytes straight to object storage. Bytes never stream through the Daguito API. The presigned signature embeds kind/mime/ size so a client cannot upload a different file than it announced.

type WebhookRunInput

type WebhookRunInput struct {
	APIURL  string
	Token   string
	Input   map[string]any
	Timeout time.Duration // optional; defaults to 90s
	// HTTPClient is an optional override. When nil, RunWebhook uses
	// http.DefaultClient with the configured timeout applied via context.
	HTTPClient *http.Client
}

WebhookRunInput is the input to RunWebhook. ApiURL is the Daguito ingest gateway root (e.g. https://ingest.daguito.com); Token is the raw sk_wh_... bearer.

type WebhookRunResult

type WebhookRunResult struct {
	OK          bool
	ExecutionID string
	Status      string
	Output      any
}

WebhookRunResult is the typed response of /h/:token. Output is the JSON value the flow produced — its shape is flow-dependent.

func RunWebhook

func RunWebhook(ctx context.Context, input WebhookRunInput) (*WebhookRunResult, error)

RunWebhook fires a one-shot HTTP POST to /h/:token and returns the final flow output. Use WebhookStreamSession instead for token-by-token streaming.

The context controls both connection and read deadlines — cancel it to abort an in-flight request.

type WebhookRunStreamInput added in v0.5.5

type WebhookRunStreamInput struct {
	APIURL string
	// WebhookID is the streaming webhook id ("wh_..."). Resolve via
	// Client.Flows.ResolveWebhook when only the slug is known.
	WebhookID string
	// Token is the webhook bearer ("sk_wh_...").
	Token string
	// Input is the free-form payload forwarded to the flow as base_input.
	Input map[string]any
	// Text is the inline message text sent on the WS. Defaults to a single
	// space when empty — webhook agents typically read everything from
	// base_input and don't need a user-facing message.
	Text string
	// SessionKey is an optional caller-supplied id. A fresh uuid is minted
	// when empty.
	SessionKey string
	// Timeout caps how long the SDK waits for flow.completed. No default —
	// WS has no edge timeout, so this is opt-in.
	Timeout time.Duration
}

WebhookRunStreamInput is the input to RunWebhookStream. Mirrors WebhookRunInput but adds WebhookID (resolve via Client.Flows.ResolveWebhook) since the streaming surface lives at /v1/webhooks/:id/stream rather than /h/:token.

type WebhookRunStreamResult added in v0.5.5

type WebhookRunStreamResult struct {
	OK          bool
	ExecutionID string
	// Status is "completed", "failed" or "unknown".
	Status    string
	Output    any
	ElapsedMs int64
}

WebhookRunStreamResult mirrors WebhookRunResult plus ElapsedMs measured client-side from session.started to flow.completed.

func RunWebhookStream added in v0.5.5

func RunWebhookStream(ctx context.Context, input WebhookRunStreamInput) (*WebhookRunStreamResult, error)

RunWebhookStream opens a streaming WebSocket session, sends one message, waits for flow.completed, closes the session, and returns the final output. Same ergonomics as RunWebhook (single call, one return) without the 100s Cloudflare HTTP edge timeout — use it for flows that may run longer than a HTTP request is willing to wait (long generations, vision pipelines, multi-step tools).

The shape of the returned value matches WebhookRunResult so callers can swap RunWebhook for RunWebhookStream without touching their parsing code, modulo the extra ElapsedMs field.

The context controls the dial and the wait for flow.completed — cancel it to abort the in-flight run. Timeout, when set, applies on top via context.WithTimeout.

type WebhookStreamOptions

type WebhookStreamOptions struct {
	APIURL    string
	WebhookID string
	Token     string

	// SessionKey is an optional caller-supplied id for resuming a session.
	// When empty, the SDK mints a random one.
	SessionKey string

	// BaseInput is applied to every send when the caller doesn't pass one
	// explicitly. Useful for static metadata (user_id, locale, …).
	BaseInput map[string]any

	// Scope is the server-enforced metadata filter for KB searches in this
	// session. Only primitive values (string, int, float, bool) are
	// forwarded — arrays/objects are silently dropped at the wire boundary.
	// The LLM never sees these values; Daguito injects them at the tool
	// boundary so a hallucinated id can't widen scope or leak across
	// conversations.
	Scope map[string]any

	// AutoReconnect re-opens the socket transparently on unexpected drops.
	// Reuses the same SessionKey so the daguito server resumes the running
	// flow execution — consumers don't see an EventClosed and Events() keeps
	// delivering. The new handshake re-sends session.start, then drains any
	// `pending` sends queued during the outage. Default false (opt-in) to
	// preserve the historical one-shot semantics for chatbot turns; long-
	// lived bridges (audio/video consultations, monitoring loops) should
	// flip this on.
	AutoReconnect bool
}

WebhookStreamOptions configures a WebhookStreamSession.

type WebhookStreamSession

type WebhookStreamSession struct {
	// contains filtered or unexported fields
}

WebhookStreamSession is a long-lived bidirectional session for streaming webhooks (WS /v1/webhooks/:id/stream).

Lifecycle:

s := NewWebhookStreamSession(opts)
if err := s.Connect(ctx); err != nil { ... }
defer s.Close()
for evt := range s.Events() {
    switch evt.Type {
    case EventNodeToken: ...
    case EventFlowCompleted: return
    }
}

All methods are safe for concurrent use. Events() is single-consumer — call it once per session.

func NewWebhookStreamSession

func NewWebhookStreamSession(opts WebhookStreamOptions) *WebhookStreamSession

NewWebhookStreamSession constructs a session. No I/O happens here — call Connect to open the socket.

func (*WebhookStreamSession) Close

func (s *WebhookStreamSession) Close() error

Close tears down the session. Safe to call multiple times.

func (*WebhookStreamSession) Connect

func (s *WebhookStreamSession) Connect(ctx context.Context) error

Connect opens the WebSocket and runs the auth + session.start handshake. Subsequent calls are no-ops. The provided context governs only the dial; the long-lived recv loop runs until Close.

func (*WebhookStreamSession) Events

func (s *WebhookStreamSession) Events() <-chan StreamEvent

Events returns the channel of typed StreamEvents. The channel is closed when the session ends (either Close was called or the server closed the socket). Range over it in a single goroutine.

func (*WebhookStreamSession) RegisterTool

func (s *WebhookStreamSession) RegisterTool(spec ToolSpec, handler ToolHandler) error

RegisterTool registers a client-side function tool the LLM may invoke. The spec is auto-injected into base_input.client_tools on every send; when the server emits agent.tool_call_started for this tool, handler runs locally and its return value is fed back via a tool_result frame.

RegisterTool can be called before or after Connect. Registering twice with the same name replaces the previous handler.

func (*WebhookStreamSession) Send

func (s *WebhookStreamSession) Send(ctx context.Context, msg SendableMessage, baseInput map[string]any) error

Send pushes a message into the active session. If the session has not completed its handshake yet, the message is queued and dispatched once session.started arrives — callers do not need to wait themselves.

baseInput overrides the session-level BaseInput for this single send. Pass nil to fall back to the session default.

func (*WebhookStreamSession) SendRaw

func (s *WebhookStreamSession) SendRaw(ctx context.Context, frame map[string]any) error

SendRaw transmits an arbitrary control frame. Escape hatch for protocol extensions (session.open for stream-trigger flows, etc.). Most callers should use Send.

Directories

Path Synopsis
examples
admin_keys command
Administer API keys + budgets programmatically with daguito.NewClient.
Administer API keys + budgets programmatically with daguito.NewClient.
flows_migrate command
Declare flows as code and idempotently apply them to Daguito.
Declare flows as code and idempotently apply them to Daguito.
run_webhook command
One-shot webhook example.
One-shot webhook example.
smoke command
Smoke test: connect to local Daguito API on :4001 against the midulabs flow, send a text message, print every event until flow.completed.
Smoke test: connect to local Daguito API on :4001 against the midulabs flow, send a text message, print every event until flow.completed.
stream_session command
Streaming session example.
Streaming session example.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL