Skip to main content

cognee.serve()

Description

Connect the local Cognee Python SDK to Cognee Cloud or another remote Cognee API server. After serve() connects, high-level SDK operations route to the remote instance instead of local storage. You can call methods on the returned CloudClient, or continue using top-level operations such as cognee.remember(), cognee.recall(), cognee.improve(), and cognee.forget(). Use cognee.disconnect() to clear the active remote client and return the SDK to local mode.
serve() changes where SDK operations execute. It does not copy existing local datasets to the remote instance. Use push() to upload an already-built local graph, or call remember() after connecting to ingest directly into the remote instance.

Connection resolution

serve() resolves the remote target in this order:
  1. Explicit url and api_key arguments
  2. COGNEE_SERVICE_URL and COGNEE_API_KEY environment variables
  3. The saved connection from a previous successful serve() — reused only when it has both a URL and an API key
If none of these applies, serve() raises a CogneeConfigurationError that lists the ways to connect. There is no interactive login. A resolved url — from either of the first two steps — connects directly and, on success, is saved to ~/.cognee/cloud_credentials.json. Only a bare serve() reaches step 3. A connection made without an API key (a local server with access control off) is saved but not reused: pass its url again.
The saved file holds service_url, api_key and tenant_id. Files written by older releases still load; their Auth0 tokens and other unknown keys are ignored, but a tenant_id saved by the old cloud login is kept and reused as is.

Tenant lookup

After the credential probe accepts the connection, serve() calls GET /api/v1/users/me on the instance and records the tenant_id it reports for the API key’s user. On Cognee Cloud this is your cloud tenant; a self-hosted server reports its own local tenant. The id is saved with the connection and used only to tag telemetry events while the process is connected. The lookup never fails serve() and delays it by at most 5 seconds: a timeout, a non-200 response or a value that is not a UUID leaves the tenant empty while the connection proceeds. A saved connection without a tenant_id (written by an older release, or saved after a failed lookup) gets the lookup on its next bare serve(), and the result is written back to the file; if that write fails, serve() still connects.

Credentials are verified at connect time

/health is unauthenticated, so it cannot tell a working API key from a rejected one. serve() therefore also probes an authenticated endpoint (GET /api/v1/datasets) before it reports a connection, so a bad key fails here instead of on your first real operation. When a url is resolved (the direct path): The probe runs over the same HTTP session as every later remote call, and that session honours HTTP_PROXY / HTTPS_PROXY / NO_PROXY. A key rejected through the proxy (for example, a credential proxy that did not substitute the real key) therefore fails at connect time; an instance the proxy cannot reach is treated like any unreachable instance — a warning, then errors on first use. See Proxy environment variables. A saved connection goes through the same probe, with one difference: on that path both a rejected key and an unreachable instance raise (the third error below) rather than producing a connection that 401s on every call.

Errors

serve() raises CogneeConfigurationError (importable from cognee.exceptions) in these cases:
  • The instance rejected the key — name="ServeAuthenticationError", the 401/403 case above, on the direct path. Nothing is saved.
  • Nothing to connect with — a bare serve() with no environment variables and no saved connection that has an API key. name="ServeConfigurationError"; the message lists the ways to connect.
  • The saved connection no longer works — a bare serve() whose saved instance is unreachable or whose API key was rejected. Also name="ServeConfigurationError"; the message names the credentials file and the saved instance URL, and suggests deleting the file if the connection is stale.
Passing url to a server that requires authentication without also passing api_key is a configuration error, not a silent downgrade: the probe returns 401 and serve() raises. A server with its default posture requires authentication — REQUIRE_AUTHENTICATION inherits from ENABLE_BACKEND_ACCESS_CONTROL, which is on by default, and setting it to false alone is ignored while access control is on — so serve(url="http://localhost:8000") needs an API key there. Only a server running with ENABLE_BACKEND_ACCESS_CONTROL=false, which also turns the auth requirement off, falls back to its default user and answers the probe without a key.

Parameters

Optional[str]
default:"None"
Remote Cognee instance URL. When omitted, Cognee reads COGNEE_SERVICE_URL, then the saved connection.
Optional[str]
default:"None"
API key for the remote instance. When omitted, Cognee reads COGNEE_API_KEY. The saved connection’s key is used only by a bare serve() (no url and no COGNEE_SERVICE_URL), which then ignores any api_key or COGNEE_API_KEY you set. A server running with ENABLE_BACKEND_ACCESS_CONTROL=false does not require it.

Returns

A CloudClient configured for the connected instance. The returned client exposes the main remote operations:
method
Ingest data and build memory on the remote instance.
method
Write a single session-memory entry on the remote instance.
method
Query memory from the remote instance.
method
Run enrichment or session-bridging on remote memory.
method
Delete remote data, datasets, or memory state.
method
Ingest data on the remote instance without building the graph.
method
Build the knowledge graph on the remote instance.
Query the remote knowledge graph.
method
Replace one document in place on the remote instance via PATCH /api/v1/update.
method
List the documents in a remote dataset via GET /api/v1/datasets/{dataset_id}/data.

Operations that route to the remote instance

While a connection is active, these top-level SDK calls are proxied to the remote instance instead of touching local storage — you do not have to call the CloudClient method yourself: Routing happens before any local resolution, so these calls work against datasets that exist only on the remote instance, and they write nothing to the local store.
The remote routes accept a narrower parameter surface than their local counterparts. update() proxies only data_id, data, dataset_id, node_set, and chunk_level_diff; anything else you pass is dropped and the server applies its own configuration. Most of the dropped parameters are named in a logged warning, but user, incremental_loading, and data_cache go silently. See update() for the full list. recall() likewise forwards only part of its parameters; see recall() for which ones.

Examples

Disconnecting

disconnect() closes the active remote connection for the current SDK process. The saved connection is not deleted, so a later bare serve() can reconnect to it when it has an API key that still works. Use cognee-cli serve --logout (or cognee.disconnect(clear_saved=True)) to also delete it.

See also