clientsdk

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Aug 17, 2026 License: Apache-2.0 Imports: 12 Imported by: 0

README

NeKiro Workspace Client SDK for Go

clientsdk lets application code invoke Agents already installed in one NeKiro Workspace. It talks only to the Control Plane Gateway. It never accepts an Agent endpoint, Router address, version, Release, Card digest, or Agent credential.

Installation remains a separate, explicit Gateway workflow:

Discover -> accept permissions -> install into Workspace
                                      |
                                      v
                         clientsdk Invoke / InvokeStream

The SDK does not discover, install, enable, upgrade, deploy, or replace an Agent during invocation.

Configure one Workspace client

client, err := clientsdk.NewClient(clientsdk.Config{
    HTTPClient:            &http.Client{Timeout: 30 * time.Second},
    GatewayOrigin:         "https://api.nekiro.dev",
    WorkspaceID:           "workspace-production",
    ApplicationCredential: os.Getenv("NEKIRO_APPLICATION_CREDENTIAL"),
    RequestLimitBytes:     1 << 20,
    ResponseLimitBytes:    4 << 20,
    StreamEventLimitBytes: 256 << 10,
})

Every field is required. The Gateway origin must be one exact canonical HTTP(S) origin, and the caller supplies its own HTTP timeout/transport policy and all byte limits. NewClient clones the HTTP client and rejects redirects; it does not select http.DefaultClient, retry, normalize the origin, or invent limits.

The application credential is an opaque Bearer supplied out of band and mapped by Gateway to the existing Workspace Owner in Phase 1. Keep the raw value in process-local secret configuration. Do not commit, print, serialize, or pass it in an invocation body. The SDK neither issues nor persists it and has no credential accessor.

Invoke an installed Agent

result, err := client.Invoke(ctx, clientsdk.InvokeRequest{
    AgentID:    "summarizer",
    Capability: "document.summarize",
    Input:      json.RawMessage(`{"document":"..."}`),
})

The per-call request has exactly Agent ID, capability, and a duplicate-free JSON object. Gateway owns Workspace authorization, installed-version and verified-Release resolution, endpoint selection, Router dispatch, and Invocation/Task/Trace assignment. A successful Result exposes those three correlation identifiers and the raw Agent output.

Handle typed platform failures

var platformError *clientsdk.PlatformError
if errors.As(err, &platformError) {
    switch platformError.Code {
    case contracts.ErrorCodeAgentNotInstalled:
        // Installation is required before another invocation.
    case contracts.ErrorCodeInstallationDisabled:
        // The Workspace owner must explicitly enable the Installation.
    case contracts.ErrorCodeAgentReleaseRevoked:
        // The exact installed Release is no longer invocable.
    }
}

PlatformError contains only validated HTTP status, stable code, Trace, and an optional complete Invocation/root Task pair. Correlated() reports whether that pair exists. Raw error bodies, fixed messages, credentials, provider details, and unknown members are never retained or exposed. Transport and caller-context errors remain local errors and preserve errors.Is.

Consume a live stream

stream, err := client.InvokeStream(ctx, request)
if err != nil {
    return err
}
defer stream.Close()

for {
    event, err := stream.Recv()
    if errors.Is(err, io.EOF) {
        break
    }
    if err != nil {
        return err
    }
    consume(event)
}

One Stream has one consumer. Recv validates the first accepted event, contiguous sequence and chunk indices, correlation, terminal event, and every bounded compact SSE frame. Completion is clean only after a terminal event is followed by actual EOF. Calling Close before that EOF—including immediately after receiving terminal—returns an error wrapping contracts.ErrRuntimeStreamInterrupted. Cancellation comes from the caller's context; the SDK does not reconnect, replay, retry, or poll Ledger content.

See the compiled package example in example_test.go. The active wire/API contracts are published by github.com/NeKiro-project/NeKiro/contracts.

Documentation

Overview

Package clientsdk invokes installed NeKiro Agents through the platform Gateway. It is an application-facing SDK and is intentionally separate from the Agent SDK used for trusted nested Agent-to-Agent calls.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Client

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

Client invokes installed Agents through one configured Gateway and Workspace. A Client is immutable after construction and safe for concurrent independent calls.

Example
package main

import (
	"context"
	"encoding/json"
	"errors"
	"io"
	"net/http"
	"os"
	"time"

	"github.com/NeKiro-project/NeKiro/contracts"
	clientsdk "github.com/NeKiro-project/nekiro-sdk-go/client"
)

func main() {
	// Installation is a separate, explicit Gateway operation. Once an Agent is
	// installed and enabled, application code binds one Client to that
	// Workspace and never supplies an endpoint, version, Release, or Router.
	client, err := clientsdk.NewClient(clientsdk.Config{
		HTTPClient:            &http.Client{Timeout: 30 * time.Second},
		GatewayOrigin:         "https://api.nekiro.dev",
		WorkspaceID:           "workspace-production",
		ApplicationCredential: os.Getenv("NEKIRO_APPLICATION_CREDENTIAL"),
		RequestLimitBytes:     1 << 20,
		ResponseLimitBytes:    4 << 20,
		StreamEventLimitBytes: 256 << 10,
	})
	if err != nil {
		return
	}

	result, err := client.Invoke(context.Background(), clientsdk.InvokeRequest{
		AgentID:    "summarizer",
		Capability: "document.summarize",
		Input:      json.RawMessage(`{"document":"..."}`),
	})
	if err != nil {
		var platformError *clientsdk.PlatformError
		if errors.As(err, &platformError) && platformError.Code == contracts.ErrorCodeAgentNotInstalled {
			// Ask the Workspace owner to install the Agent; the SDK does not
			// silently install or select another destination.
		}
		return
	}
	_ = result.Output

	stream, err := client.InvokeStream(context.Background(), clientsdk.InvokeRequest{
		AgentID:    "summarizer",
		Capability: "document.summarize",
		Input:      json.RawMessage(`{"document":"..."}`),
	})
	if err != nil {
		return
	}
	defer func() { _ = stream.Close() }()
	for {
		event, err := stream.Recv()
		if errors.Is(err, io.EOF) {
			break
		}
		if err != nil {
			return
		}
		_ = event
	}
}

func NewClient

func NewClient(config Config) (*Client, error)

NewClient validates and copies an explicit application configuration.

func (Client) Format

func (Client) Format(state fmt.State, _ rune)

Format prevents generic log formatting from exposing the Client's bound application credential or transport configuration.

func (*Client) Invoke

func (client *Client) Invoke(ctx context.Context, request InvokeRequest) (*Result, error)

Invoke performs exactly one non-streaming Gateway invocation.

func (*Client) InvokeStream

func (client *Client) InvokeStream(ctx context.Context, request InvokeRequest) (*Stream, error)

InvokeStream performs exactly one streaming Gateway invocation and returns after the HTTP status, media type, and Trace header have been validated.

type Config

type Config struct {
	HTTPClient            *http.Client
	GatewayOrigin         string
	WorkspaceID           string
	ApplicationCredential string `json:"-"`
	RequestLimitBytes     int64
	ResponseLimitBytes    int64
	StreamEventLimitBytes int64
}

Config binds one Client to one Gateway origin and Workspace authorization context. Every field is required; the SDK supplies no transport, identity, credential, or byte-limit default.

func (Config) Format

func (Config) Format(state fmt.State, _ rune)

Format prevents generic log formatting from exposing configuration fields, including the application credential.

type InvokeRequest

type InvokeRequest struct {
	AgentID    string
	Capability string
	Input      json.RawMessage
}

InvokeRequest contains the only business-controlled invocation fields. Workspace, routing, version, Release, correlation, and credentials are not accepted per call.

type PlatformError

type PlatformError struct {
	StatusCode   int
	Code         contracts.PlatformErrorCode
	TraceID      contracts.TraceID
	InvocationID string
	RootTaskID   string
}

PlatformError contains only validated, stable Gateway failure context. It deliberately does not retain the fixed wire message or raw response body.

func (*PlatformError) Correlated

func (platformError *PlatformError) Correlated() bool

Correlated reports whether Gateway returned the complete accepted Invocation and root Task identity pair.

func (*PlatformError) Error

func (platformError *PlatformError) Error() string

Error returns only the HTTP status and stable platform code.

type Result

type Result struct {
	InvocationID string
	RootTaskID   string
	TraceID      contracts.TraceID
	Output       json.RawMessage
}

Result is a validated non-streaming Gateway result.

type Stream

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

Stream owns one successful live Gateway response. It has a single consumer and is not safe for concurrent Recv or Close calls.

func (*Stream) Close

func (stream *Stream) Close() error

Close releases the response body. Until terminal followed by actual EOF has been observed, Close records and returns an interrupted-stream error.

func (*Stream) Recv

func (stream *Stream) Recv() (StreamEvent, error)

Recv returns the next validated stream event. A clean io.EOF is returned only after one terminal event has been returned and transport EOF is then observed.

type StreamEvent

StreamEvent is the active Result Stream Event v2 contract exposed after SDK framing, shape, sequence, and correlation validation.

Jump to

Keyboard shortcuts

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