Documentation
¶
Overview ¶
Package agentsdk provides a Go SDK for building custom agents that connect to agentserver via WebSocket tunnel.
Capabilities ¶
The SDK supports:
- OAuth Device Flow login (RequestDeviceCode, PollForToken)
- Agent registration and WebSocket+yamux tunnel connection
- HTTP request proxying via http.Handler
- Task polling (receive tasks assigned to this agent)
- Agent discovery (find other agents in the workspace)
- Task delegation (assign tasks to other agents)
- Async messaging (send/receive messages between agents)
Quick Start ¶
package main
import (
"context"
"fmt"
"log"
"net/http"
"github.com/agentserver/agentserver/pkg/agentsdk"
)
func main() {
ctx := context.Background()
serverURL := "https://agent.example.com"
// 1. Authenticate via OAuth Device Flow.
deviceResp, err := agentsdk.RequestDeviceCode(ctx, serverURL)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Visit: %s\n", deviceResp.VerificationURIComplete)
token, err := agentsdk.PollForToken(ctx, serverURL, deviceResp)
if err != nil {
log.Fatal(err)
}
// 2. Create client and register.
client := agentsdk.NewClient(agentsdk.Config{
ServerURL: serverURL,
Name: "my-agent",
Type: "custom",
})
reg, err := client.Register(ctx, token.AccessToken)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Registered sandbox: %s\n", reg.SandboxID)
// 3. Connect with handlers.
err = client.Connect(ctx, agentsdk.Handlers{
HTTP: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello from custom agent!")
}),
Task: func(ctx context.Context, task *agentsdk.Task) error {
result := agentsdk.TaskResult{Output: "done"}
return task.Complete(ctx, result)
},
OnConnect: func() {
log.Println("Connected!")
},
OnDisconnect: func(err error) {
log.Printf("Disconnected: %v", err)
},
})
if err != nil {
log.Fatal(err)
}
}
Agent Interaction ¶
After connecting, agents can discover and interact with other agents:
// Discover other agents in the workspace.
agents, _ := client.DiscoverAgents(ctx)
// Delegate a task to another agent.
resp, _ := client.DelegateTask(ctx, agentsdk.DelegateTaskRequest{
TargetID: agents[0].AgentID,
Prompt: "Review this code for security issues",
Skill: "code_review",
})
// Wait for the task to complete.
result, _ := client.WaitForTask(ctx, resp.TaskID, 3*time.Second)
// Send a message to another agent.
client.SendMessage(ctx, agentsdk.SendMessageRequest{
To: agents[0].AgentID,
Text: "Review complete, found 2 issues",
})
// Read incoming messages.
messages, _ := client.ReadInbox(ctx, 10)
Index ¶
- type AgentCard
- type Client
- func (c *Client) Connect(ctx context.Context, handlers Handlers, opts ...ConnectOption) error
- func (c *Client) DelegateTask(ctx context.Context, req DelegateTaskRequest) (*DelegateTaskResponse, error)
- func (c *Client) DiscoverAgents(ctx context.Context) ([]AgentCard, error)
- func (c *Client) GetTask(ctx context.Context, taskID string, includeOutput bool) (*TaskInfo, error)
- func (c *Client) ReadInbox(ctx context.Context, limit int) ([]InboxMessage, error)
- func (c *Client) Register(ctx context.Context, accessToken string) (*Registration, error)
- func (c *Client) SendMessage(ctx context.Context, req SendMessageRequest) (*SendMessageResponse, error)
- func (c *Client) SetRegistration(reg *Registration)
- func (c *Client) WaitForTask(ctx context.Context, taskID string, pollInterval time.Duration) (*TaskInfo, error)
- type Config
- type ConnectOption
- type DelegateTaskRequest
- type DelegateTaskResponse
- type DeviceAuthResponse
- type Handlers
- type InboxMessage
- type Registration
- type SendMessageRequest
- type SendMessageResponse
- type Task
- type TaskHandler
- type TaskInfo
- type TaskResult
- type TokenResponse
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type AgentCard ¶
type AgentCard struct {
AgentID string `json:"agent_id"`
DisplayName string `json:"display_name"`
Description string `json:"description"`
AgentType string `json:"agent_type"`
Status string `json:"status"` // "available", "busy", "offline"
Card json.RawMessage `json:"card"`
Version int `json:"version"`
}
AgentCard describes a discovered agent in the workspace.
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client is the agentsdk client that registers with agentserver, establishes a tunnel, and handles incoming requests.
func NewClient ¶
NewClient creates a new agent SDK client with the given configuration. If Config.Type is empty, it defaults to "custom". If Config.Name is empty, it defaults to the machine hostname.
func (*Client) Connect ¶
Connect establishes the WebSocket tunnel to agentserver and enters the main event loop. It automatically reconnects with exponential backoff on disconnection. Connect blocks until the context is cancelled.
func (*Client) DelegateTask ¶
func (c *Client) DelegateTask(ctx context.Context, req DelegateTaskRequest) (*DelegateTaskResponse, error)
DelegateTask creates a task targeting another agent in the same workspace.
func (*Client) DiscoverAgents ¶
DiscoverAgents returns all agents in the same workspace.
func (*Client) GetTask ¶
GetTask retrieves the status of a task. Set includeOutput to true to include the full task output from session events.
func (*Client) ReadInbox ¶
ReadInbox retrieves unread messages from this agent's mailbox. Messages are marked as read upon retrieval. Limit defaults to 10.
func (*Client) Register ¶
Register registers the agent with agentserver using the provided access token (obtained via the device flow). It returns a Registration containing the sandbox ID and tunnel/proxy tokens.
func (*Client) SendMessage ¶
func (c *Client) SendMessage(ctx context.Context, req SendMessageRequest) (*SendMessageResponse, error)
SendMessage sends an async message to another agent's mailbox.
func (*Client) SetRegistration ¶
func (c *Client) SetRegistration(reg *Registration)
SetRegistration sets a pre-existing registration (e.g. loaded from saved credentials) instead of calling Register.
type Config ¶
type Config struct {
ServerURL string // Base URL of agentserver (e.g. "https://agent.example.com")
Name string // Display name. Defaults to hostname.
Type string // Sandbox type. Defaults to "custom".
}
Config configures the agent client.
type ConnectOption ¶
type ConnectOption func(*connectOptions)
ConnectOption configures the Connect call.
func WithHeartbeatInterval ¶
func WithHeartbeatInterval(d time.Duration) ConnectOption
WithHeartbeatInterval sets the interval between heartbeat control messages. Default is 20 seconds.
func WithTaskPollInterval ¶
func WithTaskPollInterval(d time.Duration) ConnectOption
WithTaskPollInterval sets the interval between task poll requests. Default is 5 seconds.
type DelegateTaskRequest ¶
type DelegateTaskRequest struct {
TargetID string `json:"target_id"`
Prompt string `json:"prompt"`
Skill string `json:"skill,omitempty"`
SystemContext string `json:"system_context,omitempty"`
MaxTurns int `json:"max_turns,omitempty"`
MaxBudgetUSD float64 `json:"max_budget_usd,omitempty"`
TimeoutSeconds int `json:"timeout_seconds,omitempty"`
DelegationChain []string `json:"delegation_chain,omitempty"`
}
DelegateTaskRequest is the request body for delegating a task to another agent.
type DelegateTaskResponse ¶
type DelegateTaskResponse struct {
TaskID string `json:"task_id"`
SessionID string `json:"session_id"`
Status string `json:"status"`
}
DelegateTaskResponse is the response from creating a delegated task.
type DeviceAuthResponse ¶
type DeviceAuthResponse struct {
DeviceCode string `json:"device_code"`
UserCode string `json:"user_code"`
VerificationURI string `json:"verification_uri"`
VerificationURIComplete string `json:"verification_uri_complete"`
ExpiresIn int `json:"expires_in"`
Interval int `json:"interval"`
}
DeviceAuthResponse from RequestDeviceCode.
func RequestDeviceCode ¶
func RequestDeviceCode(ctx context.Context, serverURL string) (*DeviceAuthResponse, error)
RequestDeviceCode initiates the OAuth Device Flow by requesting a device code from the agentserver's device authorization endpoint.
type Handlers ¶
type Handlers struct {
HTTP http.Handler // Proxied HTTP requests (optional)
Task TaskHandler // Assigned tasks (optional)
OnConnect func() // Called when tunnel connected
OnDisconnect func(error) // Called when tunnel disconnected
}
Handlers defines callbacks for handling requests from agentserver.
type InboxMessage ¶
type InboxMessage struct {
ID string `json:"id"`
From string `json:"from"`
Text string `json:"text"`
MsgType string `json:"msg_type"`
CreatedAt string `json:"created_at"`
}
InboxMessage is a message received from another agent.
type Registration ¶
type Registration struct {
SandboxID string `json:"sandbox_id"`
TunnelToken string `json:"tunnel_token"`
ProxyToken string `json:"proxy_token"`
WorkspaceID string `json:"workspace_id"`
ShortID string `json:"short_id"`
}
Registration holds tokens returned after agent registration.
type SendMessageRequest ¶
type SendMessageRequest struct {
To string `json:"to"`
Text string `json:"text"`
MsgType string `json:"msg_type,omitempty"` // defaults to "text"
}
SendMessageRequest is the request body for sending a message to another agent.
type SendMessageResponse ¶
type SendMessageResponse struct {
MessageID string `json:"message_id"`
Status string `json:"status"`
}
SendMessageResponse is the response from sending a message.
type Task ¶
type Task struct {
ID string `json:"task_id"`
Skill string `json:"skill"`
Prompt string `json:"prompt"`
SystemContext string `json:"system_context"`
TimeoutSeconds int `json:"timeout_seconds"`
// contains filtered or unexported fields
}
Task represents an assigned task.
func (*Task) Complete ¶
func (t *Task) Complete(ctx context.Context, result TaskResult) error
Complete reports a task as completed with the given result.
type TaskHandler ¶
TaskHandler processes an assigned task. The context is cancelled when the tunnel connection is lost or the agent is shutting down.
type TaskInfo ¶
type TaskInfo struct {
TaskID string `json:"task_id"`
WorkspaceID string `json:"workspace_id"`
RequesterID string `json:"requester_id"`
TargetID string `json:"target_id"`
Prompt string `json:"prompt"`
Status string `json:"status"` // pending, assigned, running, completed, failed, cancelled
Skill string `json:"skill,omitempty"`
SessionID string `json:"session_id,omitempty"`
NumTurns int `json:"num_turns,omitempty"`
TotalCostUSD float64 `json:"total_cost_usd,omitempty"`
Result json.RawMessage `json:"result,omitempty"`
FailureReason string `json:"failure_reason,omitempty"`
Output string `json:"output,omitempty"`
CreatedAt string `json:"created_at"`
CompletedAt string `json:"completed_at,omitempty"`
}
TaskInfo describes the status of a delegated task.
type TaskResult ¶
type TaskResult struct {
Output string `json:"output"`
CostUSD float64 `json:"cost_usd,omitempty"`
NumTurns int `json:"num_turns,omitempty"`
}
TaskResult is the result of a completed task.
type TokenResponse ¶
type TokenResponse struct {
AccessToken string `json:"access_token"`
RefreshToken string `json:"refresh_token"`
TokenType string `json:"token_type"`
ExpiresIn int `json:"expires_in"`
Scope string `json:"scope"`
}
TokenResponse from PollForToken.
func PollForToken ¶
func PollForToken(ctx context.Context, serverURL string, deviceResp *DeviceAuthResponse) (*TokenResponse, error)
PollForToken polls the token endpoint until the user completes authorization, the device code expires, or the context is cancelled.