FAQ
Find clear answers to the most common questions about the Crusoe AI Platform. Each answer includes links to relevant guides for more details.
Getting started
How do I get an account?
An administrator creates your account. There is no public sign-up form. Your administrator will either create your account and give you a temporary password or send you an invitation link to a project. When you sign in for the first time, set your new password at https://console.codyhill.dev. For details, see create an account.
Do I have to run any infrastructure myself?
No. You provide a folder of code or a container image. The platform builds, deploys, scales, and secures your application. It handles networking, SSL certificates, and server resources automatically.
What software do I need to install?
None if you use the web console. You can write code, upload files, deploy apps, and chat with AI agents entirely in your browser. If you prefer using scripts or uploading files larger than 32 MiB, install the platformctl command-line tool. For details, see install the CLI.
Is there an API endpoint I can point my scripts at?
Yes. Use https://api.codyhill.dev. This single endpoint serves all platform features, including agents, functions, serverless services, MCP tools, secrets, Pub/Sub, MemoryStore, VectorDB, and the API gateway. The platformctl tool uses this endpoint by default. For custom HTTP requests, set your authorization header with your session token or API key. For details, see API authentication.
How much can I manage from the command line?
You can manage almost everything from the command line:
- Agents and functions: Deploy code, send requests, view logs, set secrets, manage revisions, control traffic, and view session history.
- Data and messaging services: Create, manage, and delete serverless services, Pub/Sub topics, MemoryStore databases, and VectorDB indexes.
- Platform settings: Manage organizations, projects, team members, service accounts, API keys, MCP servers, and audit logs.
Secret bindings and Crusoe Cloud connections are CLI surfaces too, not console-only: see platformctl secrets bindings --help (list, set, delete, apply) and platformctl crusoe-cloud --help (alias cc, with show, connect, disconnect, buckets, repositories, and models). For details, see the CLI overview.
Projects, access, and identity
What is the difference between an organization, a project, and a grant?
An organization owns projects and users. A project is a workspace that holds your agents, functions, secrets, and databases. Each project has its own team member list and resource limits. A grant assigns a role (member or admin) to a user or machine for a specific project. Access permissions are granted per project. For details, see projects and access.
Why do I see 404 Not Found instead of 403 Forbidden?
To protect project privacy, the platform returns 404 Not Found if you do not have permission to view a project. This prevents unauthorized users from discovering project names or resource IDs. You will see a 403 Forbidden error only if you have access to a project but lack permission for a specific action. For details, see troubleshooting.
Can platform admins access my project data?
Platform administrators manage project settings, user permissions, and resource quotas. To access data inside a project, an administrator must request a temporary break-glass access grant. Every break-glass grant requires a documented reason, appears in your project audit log, and automatically expires after a set period (4 hours by default). For details, see break-glass and audit.
How do I grant access to a CI/CD pipeline?
Create a service account in your project. A service account provides a machine identity with specific project permissions. Generate an API key for the service account and save it as an environment secret (such as CAI_TOKEN) in your CI/CD platform. API keys are shown only once when generated and can be revoked at any time. For details, see service accounts and API keys.
Can I retrieve a lost API key or invitation link?
No. Security credentials such as API keys, temporary passwords, database passwords, and invitation links are hashed upon creation and shown only once. If you lose a key or link, revoke the old credential and generate a new one.
How long does a sign-in session last?
Sign-in session tokens remain active for 12 hours. Session tokens use secure cryptographic signatures verified by the platform on each request. Revoking user access or deleting an account takes effect on the user's permissions immediately for all subsequent API requests. For automated scripts, use revocable API keys instead of session tokens.
Agents
Which agent frameworks are supported?
The platform natively supports three frameworks: ADK (Google's Agent Development Kit), LangGraph, and CrewAI. The platform automatically detects your framework based on your entry file (agent.py for ADK, graph.py for LangGraph, or crew.py for CrewAI). All deployed agents expose a unified HTTP API. For details, see the Agents overview.
How do agents maintain conversation context?
Agents use sessions to track conversation history. Every request includes a session_id. The platform stores the message history for that session and provides it to the model on each turn. Reusing the same session_id continues the conversation. Omitting the ID prompts the platform to create a new session ID and return it in the response. For details, see sessions.
What is the difference between sessions and long-term memory?
A session stores the message history for a single ongoing conversation. Long-term memory persists facts across multiple sessions. Using the memorize action extracts key information from a session and saves it to a searchable memory bank available to all future conversations with that agent. For details, see memory.
Is the memory bank private to each caller?
The memory bank belongs to the AI agent rather than an individual caller. Information stored in an agent's memory bank can be retrieved in future conversations with that agent. Because memorizing writes permanent facts to the agent, the memorize action requires user authentication. For details, see memory.
Who can invoke my deployed agent?
Invoking an agent sends messages to an active endpoint. By default, agent endpoints accept incoming requests. Managing an agent (deploying code, viewing logs, setting secrets, or deleting the agent) always requires authentication. If your application requires authentication for invoking agents, enable endpoint authentication in your project settings. For details, see invoke.
How do I change the model or use my own model API key?
Read the model name from an environment variable in your agent code rather than hardcoding it. You can update environment variables or assign a custom model API key using secrets:
platformctl secrets set my-agent MODEL_API_KEY=sk-...
Updating a secret creates a new revision that takes effect when the agent processes its next request. For details, see secrets and env.
Why did my agent code changes not take effect?
The platform uses immutable revisions. Each revision is a snapshot of your code, environment variables, and configuration settings. Updating your code or settings creates a new revision. Traffic automatically routes to the newest ready revision unless you pin traffic to a specific version. For details, see traffic and revisions.
Can I embed an agent chat widget on my website?
Yes. Enable the embed widget for your agent, add your domain to the allowed origins list, and include the provided HTML script tag on your website. Visitors can chat with your agent directly, and conversation sessions persist across page refreshes. Always specify your allowed domains to restrict unauthorized embeds. For details, see embed chat.
Compute: agents, functions, and services
Should I use an agent, a function, or a serverless service?
| You Have | Choose | Reason |
|---|---|---|
| Python AI agent code (ADK, LangGraph, or CrewAI) | Agent | Built-in session management, memory bank, tool execution, and LLM integration. |
| A single handler file in Python, Node.js, Go, or Ruby | Function | Lightweight serverless code with no container configuration required. |
| A custom Docker or container image | Serverless Service | Full control over the runtime environment, dependencies, and web framework. |
All three compute options automatically scale to zero when idle to save resources. When a new request arrives, the platform boots an instance during a brief cold start.
Can I use a custom domain name?
Yes, and natively — you do not need a reverse proxy or a CDN in front of the platform. Every workload has one canonical platform address, https://<name>-<project-short>.apps.codyhill.dev, which serves nothing until you publish the workload. To serve it on a name of your own, claim the name, create the single DNS record the command prints, then publish onto it:
platformctl gateway domain claim api.yourdomain.com
platformctl gateway publish function/my-function \
--domain api.yourdomain.com --auth none
The record is checked about once a minute. Until it appears the address is claimed but not usable, and an endpoint published on it exists and serves nothing; both start working on their own once the record shows up. Use a subdomain (api.example.com) — the top level of a domain cannot be pointed here with a CNAME, and wildcards are not supported. If you host DNS on Cloudflare, leave the record DNS Only (grey cloud): a proxied record blocks the automated TLS validation. For details, see custom domains.
Does "internal access" mean authenticated?
No. An internal workload is accessible only from within the platform's private network, but it does not validate user identity by default. If your internal service requires user authentication, verify authorization credentials inside your application handler.
Can I trigger functions or agents on a schedule or event?
Yes. A trigger automatically invokes a serverless service, function, or agent based on an event. Supported trigger types include:
- Cron schedules: Run workloads on a time-based schedule (such as every night at midnight).
- Pub/Sub messages: Run workloads when a message arrives on a Pub/Sub topic.
- Object store events: Poll a bucket and run a workload over each new object. This one behaves differently enough from the other two to be worth reading about first — see the next question.
To create triggers for functions or agents, use the CLI or API:
platformctl serverless triggers create nightly-report \
--target my-function --type schedule --cron "0 2 * * *"
The trigger's name is positional, and --type is required (schedule, pubsub, or objectstore). For agents, call /invoke on the target — --target-path /invoke on the CLI, target.path in the API. For details, see the serverless API reference.
What is different about an object store trigger?
Four things, and each one bites on the first run:
- The body is the object's content, not a description of it. The trigger POSTs the object's own bytes. There is no
Recordsarray and nobucketorkeyfield to read, and your handler needs no S3 client. In Python, a non-JSON object arrives as{"data": "<text>"}and undecodable bytes as{"data_base64": "..."}. - The object key is not delivered. CloudEvent attributes are exposed as
event["_cloudevent"], but on this source they identify the source rather than the object. Derive the identity from the content (a Markdown# heading, a field in the JSON) or put it inside the object. after_readis required and has no default. Choosemove,delete, ornone; a blank is refused. A trigger with nothing retiring the objects it has consumed re-reads them on every poll, forever, and no default for that is right for everyone.- It polls.
poll_secondsdefaults to 60, so a dropped object is never processed instantly.
For details, see object store triggers.
How do I read logs for an idle workload?
When a workload scales to zero, live log streaming pauses. To view past output, request historical logs:
platformctl logs my-agent --history
Log history persists across scale-to-zero events and revision updates, and logs are retained for 14 days by default. For details, see logs.
Where can I monitor resource metrics?
The platform provides real-time status reporting for active instances, revision readiness, sandbox availability, and database metrics. View real-time metrics using platformctl status <name> or through the web console dashboard.
Data services
Does VectorDB generate vector embeddings automatically?
No. You generate vector embeddings using your preferred embedding model and store the resulting vector arrays in VectorDB. VectorDB indexes the vectors, performs high-speed similarity searches, and filters by metadata payloads. Deployed workloads are handed the platform's own embedding endpoint in their environment as EMBED_BASE_URL and EMBED_MODEL. For details, see the VectorDB overview.
Can I change the vector dimensions of an existing index?
No. Index settings such as dimensions, distance, shards, on_disk, and quantization are fixed at creation time to ensure search performance. To change vector dimensions, create a new index with your desired configuration and re-ingest your vector data.
Match the index to your embedding model before you create it, because width is fixed at creation and a mismatch fails every upsert.
If you embed with the platform's own model — qwen-embedding, the one injected as EMBED_MODEL and served at POST /v1/embeddings — just leave dimensions out. The API, the CLI and the console all size a new index to that model's width, so the default path works. Set a width explicitly only when your vectors come from a different model. For details, see Indexes and points.
Can I connect to data services from outside the platform?
Yes. MemoryStore, VectorDB, and Pub/Sub support external endpoints for remote management and external application integration. To secure external endpoints, restrict network access using IP allowlists and manage expiring database credentials. For details, see data credential lifecycle and IP allowlists.
How is data persisted in MemoryStore and VectorDB?
- VectorDB: Vector data is written directly to persistent storage. Deleting an index removes its stored vectors.
- MemoryStore: Database persistence is enabled by default, saving data to disk continuously. Data survives container restarts and updates.
For mission-critical data, maintain your primary source data in persistent object storage or a relational database, and re-ingest vectors or cache keys as needed.
Why was my published Pub/Sub message dropped?
Pub/Sub retains messages only when an active subscription exists on the topic. Publishing to a topic that has no subscriptions succeeds but immediately reclaims the message. Create your subscription before publishing messages. For details, see topics and subscriptions.
How is the Pub/Sub storage quota calculated?
Pub/Sub storage quotas are reserved when a topic is created based on its configured max_bytes. Adjusting or deleting unused topics releases reserved quota back to your project budget. For details, see publish and consume.
Does Pub/Sub guarantee exactly-once delivery?
Pub/Sub provides at-least-once delivery. Every published message is delivered to subscribers, but network retries may occasionally cause duplicate deliveries. Design subscriber applications to be idempotent so processing the same message twice produces the same result.
Security and secrets
Where should I store sensitive API keys?
Store sensitive credentials in the platform's Secrets Manager. Map the secret to an environment variable on your workload using a secret binding, then apply the binding:
platformctl secrets bindings set my-agent SENSITIVE_KEY --secret my-secret
platformctl secrets bindings apply my-agent
--secret names a secret; it is never a value. Nothing sensitive passes through this command line — the value is written once with platformctl secrets put, which reads it from a file or a pipe.
Stored values are encrypted at rest, and secret values are never displayed in standard CLI listings or API responses. For details, see manage secrets.
Why does my agent not see a newly bound secret?
Creating a binding records intent and changes nothing that is running. Run platformctl secrets bindings apply my-agent to deliver the value. Applying reads every bound secret at its bound version, writes the values onto the workload, and rolls a new revision — a revision is an immutable snapshot, so writing the values alone would not reach anything already serving. Rotating a secret behaves the same way: the new version does not reach a running workload until you apply.
Can I inspect the plain text value of a stored secret?
Yes, if you hold the project admin role. Plain text secrets can be retrieved using the explicit reveal command. Every reveal action is recorded in the project's append-only audit log with the user identity, secret version, and timestamp. For details, see break-glass and audit.
Is code executed by my agent isolated safely?
Yes. Code executed via run_python runs inside an isolated, single-use sandbox container. Sandboxes do not carry platform credentials, cannot access internal platform infrastructure, and have restricted network access. The sandbox container is destroyed immediately after execution completes. For details, see security and limits.
Limits, cost, and monitoring
What are the main platform resource limits?
Here are the key platform limits:
| Limit | Value |
|---|---|
| Code Upload | 100 MiB (CLI) / 32 MiB (Console) |
| API Page Size | 50 items default / 200 items maximum |
| Agent Invoke Payload | 1 MiB body / 60-second execution timeout |
| Function Event Payload | 8 MiB body |
| Sandbox Snippet Runtime | 20-second timeout |
| Default Project Quota | 50 concurrent instances / 1 GiB Pub/Sub storage |
For a complete list of limits, see the limits reference.
How do I track changes in my project?
All project configuration changes, deployments, secret updates, and access grants are recorded in the project audit log. The audit log is append-only and visible to all project members in the web console or via platformctl audit (one page per run; raise --limit, up to 200, and pass the printed --page-token back for older entries). For details, see quotas and audit.
What should I do if I encounter an error?
Locate the request_id in the error response body or web console notification. Compare the error string against the troubleshooting guide and platform considerations. If the issue persists, provide the request_id and execution details to your project administrator or support team.