Something went wrong. Try again.
[READ-ONLY] Mirror of https://github.com/just-cameron/note. External storage tool for Letta agents to manage persistent notes
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207package api
import ( "bytes" "encoding/json" "fmt" "io" "net/http" "net/url" "os")
// Block represents a Letta memory blocktype Block struct { ID string `json:"id"` Label string `json:"label"` Value string `json:"value"` Description string `json:"description"`}
// Client is a Letta API clienttype Client struct { BaseURL string APIKey string HTTPClient *http.Client}
// NewClient creates a new Letta API clientfunc NewClient(baseURL string) (*Client, error) { apiKey := os.Getenv("LETTA_API_KEY") if apiKey == "" { return nil, fmt.Errorf("LETTA_API_KEY environment variable not set") }
if baseURL == "" { baseURL = "https://api.letta.com" }
return &Client{ BaseURL: baseURL, APIKey: apiKey, HTTPClient: &http.Client{}, }, nil}
// doRequest performs an HTTP request with authenticationfunc (c *Client) doRequest(method, path string, body interface{}) ([]byte, error) { var bodyReader io.Reader if body != nil { jsonBody, err := json.Marshal(body) if err != nil { return nil, fmt.Errorf("failed to marshal request body: %w", err) } bodyReader = bytes.NewReader(jsonBody) }
req, err := http.NewRequest(method, c.BaseURL+path, bodyReader) if err != nil { return nil, fmt.Errorf("failed to create request: %w", err) }
req.Header.Set("Authorization", "Bearer "+c.APIKey) req.Header.Set("Content-Type", "application/json")
resp, err := c.HTTPClient.Do(req) if err != nil { return nil, fmt.Errorf("request failed: %w", err) } defer resp.Body.Close()
respBody, err := io.ReadAll(resp.Body) if err != nil { return nil, fmt.Errorf("failed to read response: %w", err) }
if resp.StatusCode < 200 || resp.StatusCode >= 300 { return nil, fmt.Errorf("API error (status %d): %s", resp.StatusCode, string(respBody)) }
return respBody, nil}
// ListBlocks lists all blocks matching the description searchfunc (c *Client) ListBlocks(descriptionSearch string) ([]Block, error) { path := "/v1/blocks?" params := url.Values{} if descriptionSearch != "" { params.Set("description_search", descriptionSearch) } path += params.Encode()
respBody, err := c.doRequest("GET", path, nil) if err != nil { return nil, err }
var blocks []Block if err := json.Unmarshal(respBody, &blocks); err != nil { return nil, fmt.Errorf("failed to parse blocks: %w", err) }
return blocks, nil}
// GetBlock retrieves a specific block by label and ownerfunc (c *Client) GetBlock(label, ownerID string) (*Block, error) { path := "/v1/blocks?" params := url.Values{} params.Set("label", label) params.Set("description_search", ownerID) path += params.Encode()
respBody, err := c.doRequest("GET", path, nil) if err != nil { return nil, err }
var blocks []Block if err := json.Unmarshal(respBody, &blocks); err != nil { return nil, fmt.Errorf("failed to parse blocks: %w", err) }
if len(blocks) == 0 { return nil, nil }
return &blocks[0], nil}
// CreateBlock creates a new blockfunc (c *Client) CreateBlock(label, value, description string) (*Block, error) { body := map[string]string{ "label": label, "value": value, "description": description, }
respBody, err := c.doRequest("POST", "/v1/blocks", body) if err != nil { return nil, err }
var block Block if err := json.Unmarshal(respBody, &block); err != nil { return nil, fmt.Errorf("failed to parse block: %w", err) }
return &block, nil}
// UpdateBlock updates an existing blockfunc (c *Client) UpdateBlock(blockID, value string) (*Block, error) { body := map[string]string{ "value": value, }
respBody, err := c.doRequest("PATCH", "/v1/blocks/"+blockID, body) if err != nil { return nil, err }
var block Block if err := json.Unmarshal(respBody, &block); err != nil { return nil, fmt.Errorf("failed to parse block: %w", err) }
return &block, nil}
// DeleteBlock deletes a blockfunc (c *Client) DeleteBlock(blockID string) error { _, err := c.doRequest("DELETE", "/v1/blocks/"+blockID, nil) return err}
// Agent represents a Letta agenttype Agent struct { ID string `json:"id"` Name string `json:"name"` Description string `json:"description,omitempty"` CreatedAt string `json:"created_at,omitempty"`}
// ListAgents lists all agents, optionally filtered by name searchfunc (c *Client) ListAgents(nameSearch string) ([]Agent, error) { path := "/v1/agents/" params := url.Values{} if nameSearch != "" { params.Set("query_text", nameSearch) } if len(params) > 0 { path += "?" + params.Encode() }
respBody, err := c.doRequest("GET", path, nil) if err != nil { return nil, err }
var agents []Agent if err := json.Unmarshal(respBody, &agents); err != nil { return nil, fmt.Errorf("failed to parse agents: %w", err) }
return agents, nil}