oz-agent-sdk 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/AGENTS.md +23 -0
- data/CHANGELOG.md +30 -0
- data/CONTRIBUTING.md +60 -0
- data/Gemfile +6 -0
- data/LICENSE +201 -0
- data/Makefile +64 -0
- data/README.md +266 -0
- data/Rakefile +32 -0
- data/docs/api_reference.md +156 -0
- data/docs/configuration.md +84 -0
- data/docs/error_handling.md +87 -0
- data/docs/getting_started.md +92 -0
- data/docs/index.md +56 -0
- data/examples/identities.rb +35 -0
- data/examples/list_runs.rb +31 -0
- data/examples/run_agent.rb +38 -0
- data/examples/schedules.rb +31 -0
- data/lib/oz/client.rb +299 -0
- data/lib/oz/configuration.rb +46 -0
- data/lib/oz/cursor_page.rb +89 -0
- data/lib/oz/errors.rb +72 -0
- data/lib/oz/model.rb +116 -0
- data/lib/oz/resources/agent.rb +95 -0
- data/lib/oz/resources/base.rb +33 -0
- data/lib/oz/resources/conversations.rb +16 -0
- data/lib/oz/resources/identities.rb +46 -0
- data/lib/oz/resources/runs.rb +55 -0
- data/lib/oz/resources/schedules.rb +64 -0
- data/lib/oz/resources/sessions.rb +16 -0
- data/lib/oz/version.rb +5 -0
- data/lib/oz.rb +72 -0
- data/mise.toml +2 -0
- data/oz-agent-sdk.gemspec +55 -0
- metadata +184 -0
data/Rakefile
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'bundler/gem_tasks'
|
|
4
|
+
require_relative 'lib/oz/version'
|
|
5
|
+
|
|
6
|
+
begin
|
|
7
|
+
require 'rspec/core/rake_task'
|
|
8
|
+
RSpec::Core::RakeTask.new(:spec)
|
|
9
|
+
rescue LoadError
|
|
10
|
+
task :spec do
|
|
11
|
+
abort 'rspec is not available. Run `bundle install` first.'
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
begin
|
|
16
|
+
require 'rubocop/rake_task'
|
|
17
|
+
RuboCop::RakeTask.new(:rubocop)
|
|
18
|
+
rescue LoadError
|
|
19
|
+
task :rubocop do
|
|
20
|
+
abort 'rubocop is not available. Run `bundle install` first.'
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
desc 'Run the full check suite (rubocop + specs)'
|
|
25
|
+
task ci: %i[rubocop spec]
|
|
26
|
+
|
|
27
|
+
desc 'Release gem to RubyGems'
|
|
28
|
+
task release_gem: [:build] do
|
|
29
|
+
sh "gem push pkg/oz-agent-sdk-#{Oz::VERSION}.gem"
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
task default: %i[rubocop spec]
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
# API Reference
|
|
2
|
+
|
|
3
|
+
All operations hang off `client.agent`. Responses are `Oz::Model` instances (see
|
|
4
|
+
[Responses](#responses)); list endpoints that paginate return an `Oz::CursorPage`.
|
|
5
|
+
|
|
6
|
+
## Agent
|
|
7
|
+
|
|
8
|
+
### `client.agent.run(**params)` → `Oz::Model`
|
|
9
|
+
|
|
10
|
+
`POST /agent/runs` — start a new agent run.
|
|
11
|
+
|
|
12
|
+
| Param | Type | Notes |
|
|
13
|
+
| -------------------- | -------------- | -------------------------------------------------------------- |
|
|
14
|
+
| `prompt` | String | Instruction. Required unless a skill is supplied. |
|
|
15
|
+
| `config` | Hash | Cloud run config (`AmbientAgentConfig`), see below. |
|
|
16
|
+
| `conversation_id` | String | Continue an existing conversation. |
|
|
17
|
+
| `attachments` | Array<Hash> | Up to 5 `{ data:, file_name:, mime_type: }` (base64 `data`). |
|
|
18
|
+
| `interactive` | Boolean | Whether the run is interactive (default false). |
|
|
19
|
+
| `mode` | String | `"normal"`, `"plan"`, or `"orchestrate"`. |
|
|
20
|
+
| `parent_run_id` | String | Parent run for orchestration trees. |
|
|
21
|
+
| `skill` | String | Skill spec used as the base prompt. |
|
|
22
|
+
| `team` | Boolean | Create a team-owned run. |
|
|
23
|
+
| `title` | String | Custom run title. |
|
|
24
|
+
| `agent_identity_uid` | String | Execution principal (team runs only). |
|
|
25
|
+
|
|
26
|
+
Returns `{ run_id, state, task_id, at_capacity }`.
|
|
27
|
+
|
|
28
|
+
Common `config` keys: `environment_id`, `model_id`, `name`, `base_prompt`, `mcp_servers`,
|
|
29
|
+
`harness`, `harness_auth_secrets`, `inference_providers`, `memory_stores`, `skills`,
|
|
30
|
+
`skill_spec`, `computer_use_enabled`, `idle_timeout_minutes`, `session_sharing`,
|
|
31
|
+
`worker_host`.
|
|
32
|
+
|
|
33
|
+
```ruby
|
|
34
|
+
client.agent.run(
|
|
35
|
+
prompt: 'Fix the failing test',
|
|
36
|
+
config: { environment_id: 'env-123', model_id: 'claude-sonnet-4', name: 'ci-fix' }
|
|
37
|
+
)
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### `client.agent.list(**params)` → `Oz::Model`
|
|
41
|
+
|
|
42
|
+
`GET /agent` — list available agents (skills). Params: `include_malformed_skills`,
|
|
43
|
+
`refresh`, `repo` (`"owner/repo"`), `sort_by` (`"name"` | `"last_run"`). Returns
|
|
44
|
+
`{ agents: [...] }`.
|
|
45
|
+
|
|
46
|
+
### `client.agent.get_artifact(artifact_uid)` → `Oz::Model`
|
|
47
|
+
|
|
48
|
+
`GET /agent/artifacts/{uid}` — retrieve a `PLAN`, `SCREENSHOT`, or `FILE` artifact. The
|
|
49
|
+
response shape depends on `artifact_type`.
|
|
50
|
+
|
|
51
|
+
### `client.agent.list_environments(sort_by: nil)` → `Oz::Model`
|
|
52
|
+
|
|
53
|
+
`GET /agent/environments` — list cloud environments. `sort_by`: `"last_updated"` (default)
|
|
54
|
+
or `"name"`. Returns `{ environments: [...] }`.
|
|
55
|
+
|
|
56
|
+
## Runs — `client.agent.runs`
|
|
57
|
+
|
|
58
|
+
### `retrieve(run_id)` → `Oz::Model`
|
|
59
|
+
|
|
60
|
+
`GET /agent/runs/{id}` — a single run (`RunItem`).
|
|
61
|
+
|
|
62
|
+
### `list(**params)` → `Oz::CursorPage`
|
|
63
|
+
|
|
64
|
+
`GET /agent/runs` — cursor-paginated runs. Filters: `ancestor_run_id`, `artifact_type`,
|
|
65
|
+
`created_after`, `created_before`, `creator`, `cursor`, `environment_id`,
|
|
66
|
+
`execution_location`, `executor`, `limit`, `model_id`, `name`, `q`, `schedule_id`, `skill`,
|
|
67
|
+
`skill_spec`, `sort_by`, `sort_order`, `source`, `state` (Array), `updated_after`.
|
|
68
|
+
|
|
69
|
+
Time-valued filters accept a `Time`/`Date` or an ISO-8601 String. `state` is encoded as
|
|
70
|
+
repeated query keys.
|
|
71
|
+
|
|
72
|
+
```ruby
|
|
73
|
+
page = client.agent.runs.list(state: %w[INPROGRESS], created_after: Time.now - 86_400)
|
|
74
|
+
page.auto_paging_each { |run| puts run.run_id }
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### `cancel(run_id)` → `String`
|
|
78
|
+
|
|
79
|
+
`POST /agent/runs/{id}/cancel` — cancel an in-progress run. Returns a confirmation string.
|
|
80
|
+
|
|
81
|
+
### `list_handoff_attachments(run_id)` → `Oz::Model`
|
|
82
|
+
|
|
83
|
+
`GET /agent/runs/{id}/handoff/attachments`.
|
|
84
|
+
|
|
85
|
+
### `submit_followup(run_id, message: nil, mode: nil)` → `Oz::Model`
|
|
86
|
+
|
|
87
|
+
`POST /agent/runs/{id}/followups` — send a follow-up message (`mode`: `"normal"` | `"plan"`
|
|
88
|
+
| `"orchestrate"`).
|
|
89
|
+
|
|
90
|
+
## Schedules — `client.agent.schedules`
|
|
91
|
+
|
|
92
|
+
### `create(cron_schedule:, name:, **params)` → `Oz::Model`
|
|
93
|
+
|
|
94
|
+
`POST /agent/schedules`. Optional: `agent_config`, `agent_uid`, `enabled`, `mode`, `prompt`,
|
|
95
|
+
`team`.
|
|
96
|
+
|
|
97
|
+
### `retrieve(schedule_id)` / `update(schedule_id, **params)` / `list` → `Oz::Model`
|
|
98
|
+
|
|
99
|
+
`GET` / `PUT /agent/schedules/{id}`, and `GET /agent/schedules` (returns `{ schedules: [...] }`).
|
|
100
|
+
|
|
101
|
+
### `delete(schedule_id)` → `Oz::Model`
|
|
102
|
+
|
|
103
|
+
`DELETE /agent/schedules/{id}` — returns `{ success: Boolean }`.
|
|
104
|
+
|
|
105
|
+
### `pause(schedule_id)` / `resume(schedule_id)` → `Oz::Model`
|
|
106
|
+
|
|
107
|
+
`POST /agent/schedules/{id}/pause` and `.../resume`.
|
|
108
|
+
|
|
109
|
+
## Agent identities — `client.agent.identities`
|
|
110
|
+
|
|
111
|
+
### `create(name:, **params)` → `Oz::Model`
|
|
112
|
+
|
|
113
|
+
`POST /agent/identities`. Optional: `description`, `prompt`, `base_model`, `base_harness`,
|
|
114
|
+
`environment_id`, `mcp_servers`, `memory_stores`, `secrets`, `skills`, `inference_providers`,
|
|
115
|
+
`harness_auth_secrets`.
|
|
116
|
+
|
|
117
|
+
### `update(uid, **params)` / `list` / `retrieve(uid)` / `delete(uid)`
|
|
118
|
+
|
|
119
|
+
`PUT /agent/identities/{uid}`, `GET /agent/identities` (`{ agents: [...] }`),
|
|
120
|
+
`GET /agent/identities/{uid}` (aliased as `get`), and `DELETE /agent/identities/{uid}`
|
|
121
|
+
(returns `nil`).
|
|
122
|
+
|
|
123
|
+
## Sessions & Conversations
|
|
124
|
+
|
|
125
|
+
### `client.agent.sessions.check_redirect(session_uuid)` → `Oz::Model`
|
|
126
|
+
|
|
127
|
+
`GET /agent/sessions/{uuid}/redirect`.
|
|
128
|
+
|
|
129
|
+
### `client.agent.conversations.check_redirect(conversation_id)` → `Oz::Model`
|
|
130
|
+
|
|
131
|
+
`GET /agent/conversations/{id}/redirect`.
|
|
132
|
+
|
|
133
|
+
## Responses
|
|
134
|
+
|
|
135
|
+
`Oz::Model` wraps decoded JSON. Fields are reachable as methods and via `[]`; nested
|
|
136
|
+
objects/arrays are wrapped recursively; booleans get a `?` predicate; unknown/absent fields
|
|
137
|
+
return `nil`.
|
|
138
|
+
|
|
139
|
+
```ruby
|
|
140
|
+
run.state # method access
|
|
141
|
+
run['run_id'] # bracket access (String or Symbol key)
|
|
142
|
+
run.at_capacity? # predicate
|
|
143
|
+
run.agent_config.model_id # nested
|
|
144
|
+
run.key?('schedule') # presence check
|
|
145
|
+
run.to_h # plain Hash (string keys, deep)
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## Pagination
|
|
149
|
+
|
|
150
|
+
`Oz::CursorPage` is `Enumerable` over the current page and provides:
|
|
151
|
+
|
|
152
|
+
- `data` — Array of `Oz::Model` for the page.
|
|
153
|
+
- `next_page?` / `next_page` — fetch the next page (reuses filters + new cursor).
|
|
154
|
+
- `auto_paging_each` — iterate every item across all pages (returns an `Enumerator`
|
|
155
|
+
without a block).
|
|
156
|
+
- `has_next_page`, `next_cursor`, `size`, `empty?`.
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Configuration
|
|
2
|
+
|
|
3
|
+
## Client options
|
|
4
|
+
|
|
5
|
+
`Oz::Client.new` accepts the following keyword arguments:
|
|
6
|
+
|
|
7
|
+
| Option | Default | Description |
|
|
8
|
+
| ----------------- | ---------------------------------- | ---------------------------------------------------- |
|
|
9
|
+
| `api_key` | `ENV['WARP_API_KEY']` | Bearer token for authentication. |
|
|
10
|
+
| `base_url` | `https://app.warp.dev/api/v1` | API base URL (or `ENV['OZ_API_BASE_URL']`). |
|
|
11
|
+
| `timeout` | `60` | Per-request timeout in seconds. |
|
|
12
|
+
| `max_retries` | `2` | Retries for transient failures (`0` disables). |
|
|
13
|
+
| `default_headers` | `{}` | Extra headers sent on every request. |
|
|
14
|
+
| `logger` | `nil` | A `Logger`; enables Faraday request/response logging.|
|
|
15
|
+
| `adapter` | `Faraday.default_adapter` | Faraday adapter override. |
|
|
16
|
+
|
|
17
|
+
```ruby
|
|
18
|
+
require 'logger'
|
|
19
|
+
|
|
20
|
+
client = Oz::Client.new(
|
|
21
|
+
api_key: ENV.fetch('WARP_API_KEY'),
|
|
22
|
+
timeout: 120,
|
|
23
|
+
max_retries: 4,
|
|
24
|
+
default_headers: { 'X-Request-Source' => 'my-app' },
|
|
25
|
+
logger: Logger.new($stdout)
|
|
26
|
+
)
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Global configuration
|
|
30
|
+
|
|
31
|
+
Set defaults once at boot. Every `Oz::Client.new` (and the shared `Oz.client`) inherits them
|
|
32
|
+
unless overridden per call.
|
|
33
|
+
|
|
34
|
+
```ruby
|
|
35
|
+
Oz.configure do |config|
|
|
36
|
+
config.api_key = ENV.fetch('WARP_API_KEY')
|
|
37
|
+
config.base_url = 'https://app.warp.dev/api/v1'
|
|
38
|
+
config.timeout = 60
|
|
39
|
+
config.max_retries = 3
|
|
40
|
+
config.default_headers = { 'X-Request-Source' => 'my-app' }
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Lazily-built shared client using the global configuration:
|
|
44
|
+
Oz.client.agent.list
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Environment variables
|
|
48
|
+
|
|
49
|
+
| Variable | Description |
|
|
50
|
+
| ----------------------- | ----------------------------------------------------------------- |
|
|
51
|
+
| `WARP_API_KEY` | Bearer token used to authenticate requests. |
|
|
52
|
+
| `OZ_API_BASE_URL` | Override the API base URL. |
|
|
53
|
+
| `OZ_API_CUSTOM_HEADERS` | Extra headers, one `Key: Value` per line, added to every request. |
|
|
54
|
+
|
|
55
|
+
Precedence for each setting is: **explicit argument → environment variable → global
|
|
56
|
+
configuration → built-in default**.
|
|
57
|
+
|
|
58
|
+
`OZ_API_CUSTOM_HEADERS` is parsed as newline-separated `Key: Value` pairs:
|
|
59
|
+
|
|
60
|
+
```sh
|
|
61
|
+
export OZ_API_CUSTOM_HEADERS="X-Team: platform
|
|
62
|
+
X-Trace: enabled"
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Retries and backoff
|
|
66
|
+
|
|
67
|
+
Transient failures are retried automatically:
|
|
68
|
+
|
|
69
|
+
- Connection errors and timeouts.
|
|
70
|
+
- HTTP `408`, `409`, `429`, and any `5xx` response.
|
|
71
|
+
|
|
72
|
+
Backoff is exponential with jitter, starting at 0.5s and capped at 8s. A numeric
|
|
73
|
+
`Retry-After` response header is honoured when present. Disable retries with
|
|
74
|
+
`max_retries: 0`.
|
|
75
|
+
|
|
76
|
+
## Timeouts
|
|
77
|
+
|
|
78
|
+
`timeout` sets the overall request timeout (seconds). The connection-open timeout is derived
|
|
79
|
+
as `min(timeout, 10)`.
|
|
80
|
+
|
|
81
|
+
## Thread safety
|
|
82
|
+
|
|
83
|
+
A client is safe to share for sequential use. For heavily concurrent workloads, prefer one
|
|
84
|
+
client per thread.
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# Error Handling
|
|
2
|
+
|
|
3
|
+
Every failure raised by the SDK descends from `Oz::Error`. API failures specifically raise
|
|
4
|
+
`Oz::APIError` subclasses that carry useful metadata.
|
|
5
|
+
|
|
6
|
+
## Hierarchy
|
|
7
|
+
|
|
8
|
+
```
|
|
9
|
+
StandardError
|
|
10
|
+
└── Oz::Error
|
|
11
|
+
├── Oz::ConfigurationError
|
|
12
|
+
└── Oz::APIError
|
|
13
|
+
├── Oz::APIConnectionError
|
|
14
|
+
│ └── Oz::APITimeoutError
|
|
15
|
+
└── Oz::APIStatusError
|
|
16
|
+
├── Oz::BadRequestError (400)
|
|
17
|
+
├── Oz::AuthenticationError (401)
|
|
18
|
+
├── Oz::PermissionDeniedError (403)
|
|
19
|
+
├── Oz::NotFoundError (404)
|
|
20
|
+
├── Oz::ConflictError (409)
|
|
21
|
+
├── Oz::UnprocessableEntityError (422)
|
|
22
|
+
├── Oz::RateLimitError (429)
|
|
23
|
+
└── Oz::InternalServerError (5xx)
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Error metadata
|
|
27
|
+
|
|
28
|
+
`Oz::APIError` exposes:
|
|
29
|
+
|
|
30
|
+
| Method | Description |
|
|
31
|
+
| ------------- | -------------------------------------------------------------- |
|
|
32
|
+
| `message` | Human-readable message (includes server `detail`/`title`). |
|
|
33
|
+
| `status_code` | HTTP status code (`nil` for connection/timeout errors). |
|
|
34
|
+
| `code` | Machine-readable error code (e.g. `"resource_not_found"`). |
|
|
35
|
+
| `body` | The parsed response body (Hash/String), when available. |
|
|
36
|
+
| `request_id` | The `X-Request-Id` header, for correlating with server logs. |
|
|
37
|
+
| `response` | The raw Faraday response, when available. |
|
|
38
|
+
|
|
39
|
+
## Handling errors
|
|
40
|
+
|
|
41
|
+
Rescue from the most specific to the most general:
|
|
42
|
+
|
|
43
|
+
```ruby
|
|
44
|
+
begin
|
|
45
|
+
client.agent.run(prompt: 'do the thing')
|
|
46
|
+
rescue Oz::RateLimitError => e
|
|
47
|
+
warn "Rate limited; retry later. request_id=#{e.request_id}"
|
|
48
|
+
rescue Oz::AuthenticationError
|
|
49
|
+
warn 'Authentication failed — check WARP_API_KEY.'
|
|
50
|
+
rescue Oz::NotFoundError
|
|
51
|
+
warn 'Resource not found.'
|
|
52
|
+
rescue Oz::APIStatusError => e
|
|
53
|
+
warn "API error #{e.status_code} (#{e.code}): #{e.message}"
|
|
54
|
+
rescue Oz::APITimeoutError
|
|
55
|
+
warn 'Request timed out.'
|
|
56
|
+
rescue Oz::APIConnectionError => e
|
|
57
|
+
warn "Connection problem: #{e.message}"
|
|
58
|
+
rescue Oz::APIError => e
|
|
59
|
+
warn "Unexpected API error: #{e.message}"
|
|
60
|
+
end
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Machine-readable error codes
|
|
64
|
+
|
|
65
|
+
The platform returns a stable `code` for many failures. Common values include
|
|
66
|
+
`insufficient_credits`, `feature_not_available`, `external_authentication_required`,
|
|
67
|
+
`not_authorized`, `invalid_request`, `resource_not_found`, `budget_exceeded`,
|
|
68
|
+
`integration_disabled`, `integration_not_configured`, `operation_not_supported`,
|
|
69
|
+
`environment_setup_failed`, `content_policy_violation`, `conflict`,
|
|
70
|
+
`authentication_required`, `resource_unavailable`, and `internal_error`.
|
|
71
|
+
|
|
72
|
+
```ruby
|
|
73
|
+
rescue Oz::APIStatusError => e
|
|
74
|
+
case e.code
|
|
75
|
+
when 'insufficient_credits' then notify_billing
|
|
76
|
+
when 'content_policy_violation' then log_and_skip(e)
|
|
77
|
+
else raise
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Automatic retries
|
|
83
|
+
|
|
84
|
+
The client retries transient failures before raising — connection errors, timeouts, and
|
|
85
|
+
HTTP `408`, `409`, `429`, and `5xx` responses — with exponential backoff and jitter (honouring
|
|
86
|
+
a numeric `Retry-After` header). The error is only raised after retries are exhausted.
|
|
87
|
+
Configure with `max_retries:` (default `2`; `0` disables).
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# Getting Started
|
|
2
|
+
|
|
3
|
+
## Requirements
|
|
4
|
+
|
|
5
|
+
- Ruby >= 3.1 (the project defaults to **Ruby 4.0**, managed with
|
|
6
|
+
[mise](https://mise.jdx.dev) via [`mise.toml`](../mise.toml))
|
|
7
|
+
- A Warp API key (set as the `WARP_API_KEY` environment variable)
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
With Bundler, add to your `Gemfile`:
|
|
12
|
+
|
|
13
|
+
```ruby
|
|
14
|
+
gem 'oz-agent-sdk'
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
and run `bundle install`. Without Bundler:
|
|
18
|
+
|
|
19
|
+
```sh
|
|
20
|
+
gem install oz-agent-sdk
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Authentication
|
|
24
|
+
|
|
25
|
+
The client authenticates with a Bearer token. By default it reads `WARP_API_KEY` from the
|
|
26
|
+
environment:
|
|
27
|
+
|
|
28
|
+
```sh
|
|
29
|
+
export WARP_API_KEY="sk-..."
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
```ruby
|
|
33
|
+
require 'oz'
|
|
34
|
+
|
|
35
|
+
client = Oz::Client.new # picks up WARP_API_KEY
|
|
36
|
+
# or pass it explicitly:
|
|
37
|
+
client = Oz::Client.new(api_key: 'sk-...')
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
If no key is available, the constructor raises `Oz::AuthenticationError`.
|
|
41
|
+
|
|
42
|
+
## Your first agent run
|
|
43
|
+
|
|
44
|
+
```ruby
|
|
45
|
+
require 'oz'
|
|
46
|
+
|
|
47
|
+
client = Oz::Client.new
|
|
48
|
+
|
|
49
|
+
run = client.agent.run(prompt: 'Add tests for the user model')
|
|
50
|
+
puts "Started run #{run.run_id} (#{run.state})"
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
`run` is an `Oz::Model`; access fields as methods or with `[]`:
|
|
54
|
+
|
|
55
|
+
```ruby
|
|
56
|
+
run.run_id # => "a1b2c3..."
|
|
57
|
+
run.state # => "QUEUED"
|
|
58
|
+
run['task_id'] # => "a1b2c3..." (deprecated alias of run_id)
|
|
59
|
+
run.at_capacity? # => false
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Polling for completion
|
|
63
|
+
|
|
64
|
+
The run starts asynchronously. Poll `runs.retrieve` until it reaches a terminal state:
|
|
65
|
+
|
|
66
|
+
```ruby
|
|
67
|
+
TERMINAL = %w[SUCCEEDED FAILED ERROR CANCELLED].freeze
|
|
68
|
+
|
|
69
|
+
run = client.agent.run(prompt: 'Add tests for the user model')
|
|
70
|
+
|
|
71
|
+
loop do
|
|
72
|
+
current = client.agent.runs.retrieve(run.run_id)
|
|
73
|
+
puts current.state
|
|
74
|
+
break if TERMINAL.include?(current.state)
|
|
75
|
+
|
|
76
|
+
sleep 5
|
|
77
|
+
end
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Continuing a conversation
|
|
81
|
+
|
|
82
|
+
Pass `conversation_id` to continue from a previous run, or use a follow-up message:
|
|
83
|
+
|
|
84
|
+
```ruby
|
|
85
|
+
client.agent.runs.submit_followup(run.run_id, message: 'Also update the changelog')
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Next steps
|
|
89
|
+
|
|
90
|
+
- [Configuration](configuration.md) — timeouts, retries, custom headers, logging.
|
|
91
|
+
- [API Reference](api_reference.md) — the full surface area.
|
|
92
|
+
- [Error Handling](error_handling.md) — robust failure handling.
|
data/docs/index.md
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Oz Ruby SDK Documentation
|
|
2
|
+
|
|
3
|
+
The Oz Ruby SDK is an idiomatic, resource-oriented client for the
|
|
4
|
+
[Oz API](https://docs.warp.dev) — Warp's cloud agent platform.
|
|
5
|
+
|
|
6
|
+
## Contents
|
|
7
|
+
|
|
8
|
+
- [Getting Started](getting_started.md) — installation, authentication, your first run.
|
|
9
|
+
- [Configuration](configuration.md) — client options, environment variables, retries, logging.
|
|
10
|
+
- [API Reference](api_reference.md) — every resource and method.
|
|
11
|
+
- [Error Handling](error_handling.md) — the exception hierarchy and retry behaviour.
|
|
12
|
+
|
|
13
|
+
## At a glance
|
|
14
|
+
|
|
15
|
+
```ruby
|
|
16
|
+
require 'oz'
|
|
17
|
+
|
|
18
|
+
client = Oz::Client.new(api_key: ENV['WARP_API_KEY'])
|
|
19
|
+
|
|
20
|
+
run = client.agent.run(prompt: 'Fix the bug in auth.rb')
|
|
21
|
+
puts run.run_id
|
|
22
|
+
|
|
23
|
+
client.agent.runs.list(limit: 20).auto_paging_each do |r|
|
|
24
|
+
puts "#{r.run_id} #{r.state} #{r.title}"
|
|
25
|
+
end
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Resource map
|
|
29
|
+
|
|
30
|
+
| Ruby | HTTP |
|
|
31
|
+
| --------------------------------------------- | ------------------------------------------------ |
|
|
32
|
+
| `client.agent.run` | `POST /agent/runs` |
|
|
33
|
+
| `client.agent.list` | `GET /agent` |
|
|
34
|
+
| `client.agent.get_artifact` | `GET /agent/artifacts/{uid}` |
|
|
35
|
+
| `client.agent.list_environments` | `GET /agent/environments` |
|
|
36
|
+
| `client.agent.runs.retrieve` | `GET /agent/runs/{id}` |
|
|
37
|
+
| `client.agent.runs.list` | `GET /agent/runs` |
|
|
38
|
+
| `client.agent.runs.cancel` | `POST /agent/runs/{id}/cancel` |
|
|
39
|
+
| `client.agent.runs.list_handoff_attachments` | `GET /agent/runs/{id}/handoff/attachments` |
|
|
40
|
+
| `client.agent.runs.submit_followup` | `POST /agent/runs/{id}/followups` |
|
|
41
|
+
| `client.agent.schedules.create` | `POST /agent/schedules` |
|
|
42
|
+
| `client.agent.schedules.retrieve` | `GET /agent/schedules/{id}` |
|
|
43
|
+
| `client.agent.schedules.update` | `PUT /agent/schedules/{id}` |
|
|
44
|
+
| `client.agent.schedules.list` | `GET /agent/schedules` |
|
|
45
|
+
| `client.agent.schedules.delete` | `DELETE /agent/schedules/{id}` |
|
|
46
|
+
| `client.agent.schedules.pause` | `POST /agent/schedules/{id}/pause` |
|
|
47
|
+
| `client.agent.schedules.resume` | `POST /agent/schedules/{id}/resume` |
|
|
48
|
+
| `client.agent.identities.create` | `POST /agent/identities` |
|
|
49
|
+
| `client.agent.identities.update` | `PUT /agent/identities/{uid}` |
|
|
50
|
+
| `client.agent.identities.list` | `GET /agent/identities` |
|
|
51
|
+
| `client.agent.identities.retrieve` | `GET /agent/identities/{uid}` |
|
|
52
|
+
| `client.agent.identities.delete` | `DELETE /agent/identities/{uid}` |
|
|
53
|
+
| `client.agent.sessions.check_redirect` | `GET /agent/sessions/{uuid}/redirect` |
|
|
54
|
+
| `client.agent.conversations.check_redirect` | `GET /agent/conversations/{id}/redirect` |
|
|
55
|
+
|
|
56
|
+
See the [examples](../examples/) directory for runnable scripts.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Manage agent identities (team-owned execution principals).
|
|
4
|
+
#
|
|
5
|
+
# WARP_API_KEY=sk-... ruby examples/identities.rb
|
|
6
|
+
|
|
7
|
+
require 'oz'
|
|
8
|
+
|
|
9
|
+
client = Oz::Client.new
|
|
10
|
+
|
|
11
|
+
identity = client.agent.identities.create(
|
|
12
|
+
name: 'ci-bot',
|
|
13
|
+
description: 'Runs nightly maintenance tasks',
|
|
14
|
+
skills: ['warpdotdev/warp-server:.claude/skills/deploy/SKILL.md']
|
|
15
|
+
)
|
|
16
|
+
puts "Created identity #{identity.uid}"
|
|
17
|
+
|
|
18
|
+
puts 'All identities:'
|
|
19
|
+
client.agent.identities.list.agents.each do |agent|
|
|
20
|
+
puts " #{agent.uid} #{agent.name}"
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
client.agent.identities.update(identity.uid, description: 'Updated description')
|
|
24
|
+
puts 'Updated.'
|
|
25
|
+
|
|
26
|
+
# Use the identity as the execution principal for a team-owned run:
|
|
27
|
+
run = client.agent.run(
|
|
28
|
+
prompt: 'Run the nightly checks',
|
|
29
|
+
team: true,
|
|
30
|
+
agent_identity_uid: identity.uid
|
|
31
|
+
)
|
|
32
|
+
puts "Started run #{run.run_id} as identity #{identity.uid}"
|
|
33
|
+
|
|
34
|
+
client.agent.identities.delete(identity.uid)
|
|
35
|
+
puts 'Deleted identity.'
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# List recent runs, paging through all results.
|
|
4
|
+
#
|
|
5
|
+
# WARP_API_KEY=sk-... ruby examples/list_runs.rb
|
|
6
|
+
|
|
7
|
+
require 'oz'
|
|
8
|
+
|
|
9
|
+
client = Oz::Client.new
|
|
10
|
+
|
|
11
|
+
# A single page:
|
|
12
|
+
page = client.agent.runs.list(limit: 25, sort_by: 'created_at', sort_order: 'desc')
|
|
13
|
+
puts "First page: #{page.size} run(s), more available: #{page.next_page?}"
|
|
14
|
+
page.each do |run|
|
|
15
|
+
puts format(' %-38s %-11s %s', run.run_id, run.state, run.title)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
puts
|
|
19
|
+
puts 'All runs created in the last 24h that are in progress:'
|
|
20
|
+
|
|
21
|
+
filtered = client.agent.runs.list(
|
|
22
|
+
state: %w[INPROGRESS QUEUED],
|
|
23
|
+
created_after: Time.now - (24 * 60 * 60)
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
count = 0
|
|
27
|
+
filtered.auto_paging_each do |run|
|
|
28
|
+
count += 1
|
|
29
|
+
puts " #{run.run_id} #{run.state}"
|
|
30
|
+
end
|
|
31
|
+
puts "Total: #{count}"
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Run a cloud agent and poll until it finishes.
|
|
4
|
+
#
|
|
5
|
+
# WARP_API_KEY=sk-... ruby examples/run_agent.rb "Fix the bug in auth.rb"
|
|
6
|
+
#
|
|
7
|
+
# Requires the gem to be installed, or run with `bundle exec` from the repo root.
|
|
8
|
+
|
|
9
|
+
require 'oz'
|
|
10
|
+
|
|
11
|
+
prompt = ARGV.first || 'Summarize the README and suggest improvements'
|
|
12
|
+
|
|
13
|
+
client = Oz::Client.new # reads WARP_API_KEY from the environment
|
|
14
|
+
|
|
15
|
+
run = client.agent.run(
|
|
16
|
+
prompt: prompt,
|
|
17
|
+
config: {
|
|
18
|
+
# environment_id: "your-environment-id",
|
|
19
|
+
model_id: 'claude-sonnet-4',
|
|
20
|
+
name: 'sdk-example'
|
|
21
|
+
}
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
puts "Started run #{run.run_id} (state: #{run.state})"
|
|
25
|
+
|
|
26
|
+
TERMINAL = %w[SUCCEEDED FAILED ERROR CANCELLED].freeze
|
|
27
|
+
|
|
28
|
+
loop do
|
|
29
|
+
current = client.agent.runs.retrieve(run.run_id)
|
|
30
|
+
puts " #{Time.now.strftime('%H:%M:%S')} #{current.state}"
|
|
31
|
+
break if TERMINAL.include?(current.state)
|
|
32
|
+
|
|
33
|
+
sleep 5
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
final = client.agent.runs.retrieve(run.run_id)
|
|
37
|
+
puts "Finished: #{final.state}"
|
|
38
|
+
puts "Session: #{final.session_link}" if final.session_link
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Create, inspect, pause/resume, and delete a scheduled agent.
|
|
4
|
+
#
|
|
5
|
+
# WARP_API_KEY=sk-... ruby examples/schedules.rb
|
|
6
|
+
|
|
7
|
+
require 'oz'
|
|
8
|
+
|
|
9
|
+
client = Oz::Client.new
|
|
10
|
+
|
|
11
|
+
schedule = client.agent.schedules.create(
|
|
12
|
+
cron_schedule: '0 9 * * *', # daily at 09:00 UTC
|
|
13
|
+
name: 'nightly-dependency-check',
|
|
14
|
+
prompt: 'Check for outdated dependencies and open a PR if needed',
|
|
15
|
+
enabled: true
|
|
16
|
+
)
|
|
17
|
+
puts "Created schedule #{schedule.schedule_id} (#{schedule.name})"
|
|
18
|
+
|
|
19
|
+
puts 'All schedules:'
|
|
20
|
+
client.agent.schedules.list.schedules.each do |s|
|
|
21
|
+
puts " #{s.schedule_id} #{s.name} #{s.cron_schedule}"
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
client.agent.schedules.pause(schedule.schedule_id)
|
|
25
|
+
puts 'Paused.'
|
|
26
|
+
|
|
27
|
+
client.agent.schedules.resume(schedule.schedule_id)
|
|
28
|
+
puts 'Resumed.'
|
|
29
|
+
|
|
30
|
+
result = client.agent.schedules.delete(schedule.schedule_id)
|
|
31
|
+
puts "Deleted: #{result.success}"
|