|
| 1 | +# EverOS Cloud SDK — Quickstart |
| 2 | + |
| 3 | +Full usage for the Python client of the **EverOS Cloud Memory API** (v2). For an |
| 4 | +overview and install, see the [README](README.md). |
| 5 | + |
| 6 | +> **This code is generated** from the EverOS OpenAPI contract. Please file bugs and |
| 7 | +> feature requests as issues — pull requests against the generated source will be |
| 8 | +> overwritten on the next release. Corrections flow through the internal SDK factory. |
| 9 | +
|
| 10 | +## Install |
| 11 | + |
| 12 | +```sh |
| 13 | +pip install everos-cloud |
| 14 | +``` |
| 15 | + |
| 16 | +Release candidates need `--pre`: `pip install --pre everos-cloud==1.0.0rc1`. |
| 17 | + |
| 18 | +> **Upgrading from 0.4.x?** `everos-cloud` 1.0.0 is a **rewrite, not an increment**. The |
| 19 | +> 0.x line was a different client (httpx-based, hand-maintained); 1.x is generated from |
| 20 | +> the EverOS OpenAPI contract and has a different API surface — client classes, method |
| 21 | +> names, and model types all changed. The import path (`everos_cloud`) is unchanged. |
| 22 | +> Pin `everos-cloud<1` if you are not ready to migrate. |
| 23 | +
|
| 24 | +## Authentication |
| 25 | + |
| 26 | +All requests use your EverOS API key as a bearer token: |
| 27 | + |
| 28 | +```python |
| 29 | +from everos_cloud import Configuration |
| 30 | +config = Configuration(access_token="sk-...") # sent as: Authorization: Bearer sk-... |
| 31 | +``` |
| 32 | + |
| 33 | +The default host is `https://api.evermind.ai`; override with `Configuration(host=...)`. |
| 34 | + |
| 35 | +## Quickstart |
| 36 | + |
| 37 | +The snippet below exercises the six Memory endpoints. Every Memory call takes a |
| 38 | +single typed input model and returns a typed response envelope (`result.data`). |
| 39 | +Object storage lives on a separate `StorageApi` (see below). |
| 40 | + |
| 41 | +```python |
| 42 | +from everos_cloud import ApiClient, Configuration, MemoryApi |
| 43 | +from everos_cloud.models import ( |
| 44 | + AddInput, MessageItem, Content, SearchInput, GetInput, DeleteInput, |
| 45 | + EditInput, AddOperation, EditInputOperationsInner, FlushInput, |
| 46 | +) |
| 47 | + |
| 48 | +config = Configuration(access_token="sk-...") |
| 49 | + |
| 50 | +with ApiClient(config) as client: |
| 51 | + memory = MemoryApi(client) |
| 52 | + |
| 53 | + # ── Add messages ────────────────────────────────────────────────────────── |
| 54 | + # Async by default: returns HTTP 202 with status "queued" and extraction runs |
| 55 | + # in the background. Pass async_mode=False to write synchronously and surface |
| 56 | + # write errors directly. |
| 57 | + memory.add_memory(AddInput( |
| 58 | + session_id="session-1", |
| 59 | + messages=[ |
| 60 | + MessageItem( |
| 61 | + sender_id="user-1", |
| 62 | + role="user", # user | assistant | tool |
| 63 | + timestamp=1700000000, |
| 64 | + content=Content("I love hiking in the mountains"), |
| 65 | + ) |
| 66 | + ], |
| 67 | + )) |
| 68 | + |
| 69 | + # ── Search memories ─────────────────────────────────────────────────────── |
| 70 | + # method: keyword | vector | hybrid (default) | agentic |
| 71 | + result = memory.search_memory(SearchInput( |
| 72 | + query="outdoor hobbies", |
| 73 | + method="hybrid", |
| 74 | + top_k=10, |
| 75 | + include_profile=True, |
| 76 | + )) |
| 77 | + print(result.data) |
| 78 | + |
| 79 | + # ── Get memories (paginated) ────────────────────────────────────────────── |
| 80 | + # memory_type: episode | profile | agent_case | agent_skill |
| 81 | + page = memory.get_memory(GetInput( |
| 82 | + memory_type="episode", |
| 83 | + page=1, |
| 84 | + page_size=20, |
| 85 | + sort_order="desc", # by timestamp (default) |
| 86 | + )) |
| 87 | + print(page.data) |
| 88 | + |
| 89 | + # ── Edit profile (bulk, Cloud-only) ─────────────────────────────────────── |
| 90 | + # 1–50 operations; each must be wrapped in EditInputOperationsInner. |
| 91 | + # action: add | update | delete · type: explicit_info | implicit_traits |
| 92 | + memory.edit_profile(EditInput( |
| 93 | + user_id="user-1", |
| 94 | + operations=[ |
| 95 | + EditInputOperationsInner(AddOperation( |
| 96 | + action="add", |
| 97 | + type="explicit_info", |
| 98 | + data={"category": "hobby", "description": "Enjoys hiking in the mountains"}, |
| 99 | + reason="Stated in session-1", |
| 100 | + )), |
| 101 | + ], |
| 102 | + )) |
| 103 | + |
| 104 | + # ── Delete memories (scoped soft-delete, Cloud-only) ────────────────────── |
| 105 | + # Scope the delete by any combination of user_id / agent_id / session_id. |
| 106 | + memory.delete_memory(DeleteInput(user_id="user-1", session_id="session-1")) |
| 107 | + |
| 108 | + # ── Flush a session (force boundary detection + extraction) ──────────────── |
| 109 | + # Extraction is normally async; flush forces it for a session and returns |
| 110 | + # status "extracted" or "no_extraction". The generated method name mirrors |
| 111 | + # the operationId. |
| 112 | + flushed = memory.flush_api_v2_memory_flush_post(FlushInput(session_id="session-1")) |
| 113 | + print(flushed.data.status) # "extracted" | "no_extraction" |
| 114 | +``` |
| 115 | + |
| 116 | +## Uploading multimodal data (`StorageApi`) |
| 117 | + |
| 118 | +Attaching images, audio, or documents to a message is a two-step flow: ask the |
| 119 | +API to presign an upload, then `POST` the bytes directly to S3 using the returned |
| 120 | +form fields. The sign endpoint lives on `StorageApi`. |
| 121 | + |
| 122 | +Unlike the Memory endpoints, `sign_objects` returns the raw MMS envelope: business |
| 123 | +outcome is carried in `status` (`0` means success) and the payload in |
| 124 | +`result.data` — check `status == 0` before reading it. |
| 125 | + |
| 126 | +```python |
| 127 | +import requests |
| 128 | +from everos_cloud import ApiClient, Configuration, StorageApi |
| 129 | +from everos_cloud.models import SignRequest, SignObjectItem |
| 130 | + |
| 131 | +config = Configuration(access_token="sk-...") |
| 132 | + |
| 133 | +with ApiClient(config) as client: |
| 134 | + storage = StorageApi(client) |
| 135 | + |
| 136 | + # ── Presign uploads (≤ 50 objects; each file_id unique) ──────────────────── |
| 137 | + # file_type: image | file | video |
| 138 | + envelope = storage.sign_objects(SignRequest( |
| 139 | + object_list=[ |
| 140 | + SignObjectItem(file_id="file-1", file_name="photo.jpg", file_type="image"), |
| 141 | + ], |
| 142 | + )) |
| 143 | + |
| 144 | + if envelope.status != 0: # 0 == success; see status codes below |
| 145 | + raise RuntimeError(f"sign failed: status={envelope.status} error={envelope.error}") |
| 146 | + |
| 147 | + # ── Upload the bytes straight to S3 with the presigned POST form ─────────── |
| 148 | + for obj in envelope.result.data.object_list: |
| 149 | + signed = obj.object_signed_info # url + fields + maxSize |
| 150 | + with open("photo.jpg", "rb") as fh: |
| 151 | + resp = requests.post( |
| 152 | + signed.url, |
| 153 | + data=signed.fields, # presigned form fields |
| 154 | + files={"file": fh}, |
| 155 | + ) |
| 156 | + resp.raise_for_status() # 204 from S3 on success |
| 157 | + print(obj.object_key) # reference this key back in /add |
| 158 | +``` |
| 159 | + |
| 160 | +Non-zero `status` values surface business errors rather than raising — common |
| 161 | +ones are `2018` (validation failed), `1012` (bad/expired token), `1002` |
| 162 | +(unsupported `file_type`), and `1007` (more than 50 objects). See the `signObjects` |
| 163 | +description in `openapi.json` for the full list. |
| 164 | + |
| 165 | +## Methods |
| 166 | + |
| 167 | +`MemoryApi` mirrors the v2 endpoints: |
| 168 | + |
| 169 | +| Method | Endpoint | Notes | |
| 170 | +|---|---|---| |
| 171 | +| `add_memory(AddInput)` | `POST /api/v2/memory/add` | Async by default (202 `queued`); `async_mode=False` for sync 200. | |
| 172 | +| `search_memory(SearchInput)` | `POST /api/v2/memory/search` | Keyword / vector / hybrid / agentic. | |
| 173 | +| `get_memory(GetInput)` | `POST /api/v2/memory/get` | Paginated list by `memory_type`. | |
| 174 | +| `delete_memory(DeleteInput)` | `POST /api/v2/memory/delete` | Scoped soft-delete. | |
| 175 | +| `edit_profile(EditInput)` | `POST /api/v2/memory/edit` | Bulk profile add/update/delete operations. | |
| 176 | +| `flush_api_v2_memory_flush_post(FlushInput)` | `POST /api/v2/memory/flush` | Force boundary detection + extraction for a session. | |
| 177 | + |
| 178 | +`StorageApi` covers object upload: |
| 179 | + |
| 180 | +| Method | Endpoint | Notes | |
| 181 | +|---|---|---| |
| 182 | +| `sign_objects(SignRequest)` | `POST /api/v1/object/sign` | Presign ≤ 50 objects for direct-to-S3 upload; returns the MMS envelope (`status == 0` on success). | |
| 183 | + |
| 184 | +### A note on message `content` |
| 185 | + |
| 186 | +`MessageItem.content` accepts either a plain string or a list of content items. In |
| 187 | +this SDK both are passed through the `Content` wrapper: |
| 188 | + |
| 189 | +```python |
| 190 | +Content("hello") # plain text (shorthand) |
| 191 | +Content([ContentItem(type="text", text="hello")]) # explicit item list |
| 192 | +``` |
| 193 | + |
| 194 | +Either serializes to the correct wire shape. |
| 195 | + |
| 196 | +## Links |
| 197 | + |
| 198 | +- API reference: per-endpoint and model docs under [`docs/`](docs/). |
| 199 | +- Issues: https://github.com/EverMind-AI/everos-cloud-sdk-python/issues |
0 commit comments