Documentation
¶
Overview ¶
Package humanforai is a Go client for Human For AI (https://humanforai.dev), a human endpoint for AI agents: submit tasks that need physical presence, human perception, or human judgment, and a verified human operator performs them. No API key, free during the proof-of-concept pilot.
client := humanforai.New(humanforai.WithRequester("my-agent/1.0"))
sub, err := client.SubmitTask(ctx, humanforai.TaskRequest{
TaskType: "real_world_verification",
Description: "Check whether store X at address Y stocks product Z; photo proof.",
ContactEmail: "you@your-domain.com",
})
task, err := client.GetTask(ctx, sub.TaskID)
Standard library only. API reference: https://humanforai.dev/api — OpenAPI: https://humanforai.dev/openapi.json
Index ¶
- Constants
- Variables
- func SHA256Hex(text string) string
- type APIError
- type Client
- func (c *Client) AgentManifest(ctx context.Context) (map[string]any, error)
- func (c *Client) AllServices(ctx context.Context) ([]Service, error)
- func (c *Client) Do(ctx context.Context, method, path string, query url.Values, body any, ...) error
- func (c *Client) GetTask(ctx context.Context, taskID string) (*Task, error)
- func (c *Client) GetThread(ctx context.Context, messageID, accessToken string) (*Thread, error)
- func (c *Client) Health(ctx context.Context) (*Health, error)
- func (c *Client) JWKS(ctx context.Context) (*JWKS, error)
- func (c *Client) LastRateLimit() RateLimit
- func (c *Client) ListServices(ctx context.Context, limit int, cursor string) (*ServicesPage, error)
- func (c *Client) ReplyInThread(ctx context.Context, messageID, accessToken, message string) (*ReplyResult, error)
- func (c *Client) SendMessage(ctx context.Context, req MessageRequest) (*MessageResponse, error)
- func (c *Client) SubmitTask(ctx context.Context, req TaskRequest) (*TaskSubmission, error)
- func (c *Client) WaitForTask(ctx context.Context, taskID string, interval time.Duration, ...) (*Task, error)
- type Health
- type JWK
- type JWKS
- type MessageRequest
- type MessageResponse
- type Option
- type RateLimit
- type ReceiptPayload
- type Reply
- type ReplyResult
- type Service
- type ServicesPage
- type StatusEvent
- type Task
- type TaskRequest
- type TaskSubmission
- type Thread
- type VerifyOptions
Constants ¶
const DefaultBaseURL = "https://humanforai.dev"
DefaultBaseURL is the production API origin.
const Version = "0.1.1"
Version of this client, sent in the User-Agent header.
Variables ¶
var ErrReceipt = errors.New("humanforai: invalid receipt")
ErrReceipt is wrapped by every receipt verification failure.
var OutputFormats = []string{
"text_report",
"text_report_with_photos",
"structured_json",
"annotated_screenshots",
"video",
}
OutputFormats lists the deliverable formats a task can request.
var TaskTypes = []string{
"real_world_verification",
"product_or_app_testing",
"human_judgment_and_feedback",
"data_collection",
"local_physical_task",
"ai_output_review",
"prompt_and_workflow_testing",
"simulation_and_automation_testing",
"accessibility_and_usability_check",
"decision_escalation",
"custom_human_in_the_loop",
}
TaskTypes lists the task types in the service catalog. The catalog is examples, not limits: anything a human can legally and safely do is in scope; use "custom_human_in_the_loop" when nothing else fits. The live list is Client.AllServices.
Functions ¶
Types ¶
type APIError ¶
type APIError struct {
// Status is the HTTP status code.
Status int
// Code is the API's machine-readable error code, e.g. "validation_failed",
// "task_not_found", "rate_limited", "duplicate".
Code string
// Message is the human-readable explanation.
Message string
// Details lists validation details when present.
Details []string
// RateLimit holds the RateLimit headers on the failing response.
RateLimit RateLimit
// Body is the full decoded JSON body, when there was one.
Body map[string]any
}
APIError is an error response from the API (4xx/5xx).
func IsAPIError ¶
IsAPIError returns the *APIError wrapped in err, if any.
type Client ¶
type Client struct {
// BaseURL is the API origin, without a trailing slash.
BaseURL string
// Requester is sent as "requester" on tasks and "from" on messages when the
// request does not set its own (your agent or product name).
Requester string
// HTTPClient performs the requests. Defaults to a client with a 30s timeout.
HTTPClient *http.Client
// UserAgent overrides the default "humanforai-go/<version>".
UserAgent string
// contains filtered or unexported fields
}
Client talks to the Human For AI REST API.
func New ¶
New returns a Client. HUMANFORAI_BASE_URL and HUMANFORAI_REQUESTER are honoured as defaults; options override them.
func (*Client) AgentManifest ¶
AgentManifest fetches the machine-readable platform manifest (/agent.json).
func (*Client) AllServices ¶
AllServices follows the cursor until the whole catalog has been read.
func (*Client) Do ¶
func (c *Client) Do(ctx context.Context, method, path string, query url.Values, body any, headers map[string]string, out any) error
Do performs one API call and decodes the JSON body into out (which may be nil). Non-2xx responses are returned as *APIError.
func (*Client) LastRateLimit ¶
LastRateLimit returns the RateLimit headers from the most recent response.
func (*Client) ListServices ¶
ListServices returns one page of the service catalog. limit 0 means the API default; cursor "" means the first page.
func (*Client) ReplyInThread ¶
func (c *Client) ReplyInThread(ctx context.Context, messageID, accessToken, message string) (*ReplyResult, error)
ReplyInThread follows up in an existing thread.
func (*Client) SendMessage ¶
func (c *Client) SendMessage(ctx context.Context, req MessageRequest) (*MessageResponse, error)
SendMessage messages the operator.
func (*Client) SubmitTask ¶
func (c *Client) SubmitTask(ctx context.Context, req TaskRequest) (*TaskSubmission, error)
SubmitTask submits a task. Keep the returned TaskID: it is the key to the result.
func (*Client) WaitForTask ¶
func (c *Client) WaitForTask(ctx context.Context, taskID string, interval time.Duration, onUpdate func(*Task)) (*Task, error)
WaitForTask polls until the task is delivered or rejected, or ctx ends. Human review is not instant (first response within 12 hours, any day of the week, typically much faster): poll every minute or slower. Intervals under 10 seconds are raised to 10 seconds. onUpdate, when non-nil, is called after every poll.
type Health ¶
type Health struct {
Status string `json:"status"`
Service string `json:"service"`
APIVersion string `json:"api_version"`
Time string `json:"time"`
}
Health is the liveness response.
type JWK ¶
type JWK struct {
Kty string `json:"kty"`
Crv string `json:"crv"`
Kid string `json:"kid"`
X string `json:"x"`
Use string `json:"use"`
Alg string `json:"alg"`
}
JWK is one key of the receipt-signing key set.
type JWKS ¶
type JWKS struct {
Keys []JWK `json:"keys"`
}
JWKS is the published key set at /.well-known/jwks.json.
type MessageRequest ¶
type MessageRequest struct {
Message string `json:"message"`
// ReplyTo must be a real mailbox: the operator's only way to answer.
ReplyTo string `json:"reply_to"`
Subject string `json:"subject,omitempty"`
// From overrides Client.Requester for this message.
From string `json:"from,omitempty"`
IdempotencyKey string `json:"-"`
}
MessageRequest opens a thread with the operator (scoping, questions, custom work).
type MessageResponse ¶
type MessageResponse struct {
MessageID string `json:"message_id"`
CreatedAt string `json:"created_at"`
ThreadURL string `json:"thread_url"`
// AccessToken reads and replies in the thread. Keep it.
AccessToken string `json:"access_token"`
Message string `json:"message"`
}
MessageResponse is the 201 Created body.
type Option ¶
type Option func(*Client)
Option configures a Client.
func WithBaseURL ¶
WithBaseURL points the client at another origin (for example a local API).
func WithHTTPClient ¶
WithHTTPClient replaces the underlying *http.Client.
func WithRequester ¶
WithRequester sets the identifier sent with tasks and messages.
func WithUserAgent ¶
WithUserAgent replaces the User-Agent header.
type RateLimit ¶
RateLimit carries the standard RateLimit headers (draft-ietf-httpapi-ratelimit-headers) present on every API response. Zero values mean the header was absent.
type ReceiptPayload ¶
type ReceiptPayload struct {
Issuer string `json:"iss"`
TaskID string `json:"task_id"`
DeliverableSHA256 string `json:"deliverable_sha256"`
Timeline map[string]any `json:"timeline"`
// Raw holds every claim, including ones not modelled above.
Raw map[string]any `json:"-"`
}
ReceiptPayload is the decoded, verified receipt.
func VerifyReceipt ¶
func VerifyReceipt(receipt string, jwks *JWKS, opts *VerifyOptions) (*ReceiptPayload, error)
VerifyReceipt checks the signature of a compact JWS receipt against the published key set and returns its payload. Every failure wraps ErrReceipt.
type Reply ¶
type Reply struct {
Author string `json:"author"`
Message string `json:"message"`
CreatedAt string `json:"created_at"`
}
Reply is one entry of Thread.Replies.
type ReplyResult ¶
type ReplyResult struct {
MessageID string `json:"message_id"`
ReplyCount int `json:"reply_count"`
Message string `json:"message"`
}
ReplyResult is the 201 body of a thread reply.
type Service ¶
type Service struct {
ID string `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
}
Service is one entry of the catalog.
type ServicesPage ¶
type ServicesPage struct {
Items []Service `json:"items"`
Total int `json:"total"`
NextCursor string `json:"next_cursor"`
}
ServicesPage is one page of the cursor-paginated catalog.
type StatusEvent ¶
StatusEvent is one entry of Task.StatusHistory.
type Task ¶
type Task struct {
TaskID string `json:"task_id"`
Status string `json:"status"`
TaskType string `json:"task_type"`
Description string `json:"description"`
LocationRequired bool `json:"location_required"`
LocationDetail string `json:"location_detail"`
Deadline string `json:"deadline"`
OutputFormat string `json:"output_format"`
Requester string `json:"requester"`
Source string `json:"source"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
SeenByOperatorAt string `json:"seen_by_operator_at"`
ETA string `json:"eta"`
StatusHistory []StatusEvent `json:"status_history"`
RejectionReason string `json:"rejection_reason"`
// OperatorNotes carries the deliverable text (always for status_poll
// delivery, and whatever the operator chose to publish otherwise).
OperatorNotes string `json:"operator_notes"`
// Receipt, DeliverableSHA256 and ReceiptIssuedAt appear once delivered.
Receipt string `json:"receipt"`
DeliverableSHA256 string `json:"deliverable_sha256"`
ReceiptIssuedAt string `json:"receipt_issued_at"`
}
Task is the public status of a task.
type TaskRequest ¶
type TaskRequest struct {
// TaskType is one of TaskTypes (or any id from the live catalog).
TaskType string `json:"task_type"`
// Description says what to do, where, and what success looks like. The
// human cannot see your conversation context, so be self-contained.
Description string `json:"description"`
// ContactEmail receives the deliverable and clarifying questions. A real
// mailbox: placeholder domains are rejected and the domain is MX-checked.
// Required unless Delivery is "status_poll".
ContactEmail string `json:"contact_email,omitempty"`
// Delivery is "email" (default) or "status_poll": the no-mailbox path,
// where the deliverable arrives as text in Task.OperatorNotes (one such
// task per client per day).
Delivery string `json:"delivery,omitempty"`
LocationRequired *bool `json:"location_required,omitempty"`
LocationDetail string `json:"location_detail,omitempty"`
// Deadline is an ISO 8601 timestamp.
Deadline string `json:"deadline,omitempty"`
OutputFormat string `json:"output_format,omitempty"`
// Requester overrides Client.Requester for this task.
Requester string `json:"requester,omitempty"`
// IdempotencyKey makes retries safe: the same key with the same payload
// within 24h replays the original response. Sent as a header.
IdempotencyKey string `json:"-"`
}
TaskRequest describes a task for the human operator.
type TaskSubmission ¶
type TaskSubmission struct {
TaskID string `json:"task_id"`
Status string `json:"status"`
CreatedAt string `json:"created_at"`
StatusURL string `json:"status_url"`
StatusPage string `json:"status_page"`
Message string `json:"message"`
}
TaskSubmission is the 202 Accepted body returned on submission.
type Thread ¶
type Thread struct {
MessageID string `json:"message_id"`
Status string `json:"status"`
CreatedAt string `json:"created_at"`
From string `json:"from"`
Subject string `json:"subject"`
Message string `json:"message"`
Replies []Reply `json:"replies"`
ReplyCount int `json:"reply_count"`
LastReplyAt string `json:"last_reply_at"`
Note string `json:"note"`
}
Thread is a message thread with the operator.
type VerifyOptions ¶
type VerifyOptions struct {
// DeliverableText, when non-nil, must hash to the receipt's
// deliverable_sha256 (pass the task's OperatorNotes).
DeliverableText *string
// Issuer is the expected "iss" claim. Empty means DefaultBaseURL.
Issuer string
}
VerifyOptions tunes VerifyReceipt.
Directories
¶
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
humanforai
command
Command humanforai hires a verified human operator from the terminal.
|
Command humanforai hires a verified human operator from the terminal. |