tinyhumansai/openhuman · error · anyhow::Error
Managed cloud tools are disabled because your OpenHuman AI c
Error message
Managed cloud tools are disabled because your OpenHuman AI credits are exhausted. Add credits or route the task to user-supplied providers.
What it means
Thrown by IntegrationClient::ensure_budget_available before any managed call whose path starts with /agent-integrations/ (everything except /agent-integrations/pricing). It probes the hosted team usage endpoint via managed_tool_budget_exhausted (result cached for a TTL); when the OpenHuman AI credit pool that funds managed cloud tools is drained, the client fails fast instead of making the backend round-trip. A failed probe is NOT cached and lets the call through, so seeing this error means the probe succeeded and reported exhausted.
Source
Thrown at src/openhuman/integrations/client.rs:386
.expect("failed to build integration download HTTP client");
Self {
backend_url,
auth_token,
budget_config,
sdk,
download_client,
pricing: tokio::sync::OnceCell::new(),
}
}
async fn ensure_budget_available(&self, path: &str) -> anyhow::Result<()> {
if !managed_budget_applies_to_path(path) {
return Ok(());
}
if let Some(config) = &self.budget_config {
if crate::openhuman::hosted::team::managed_tool_budget_exhausted(config).await {
anyhow::bail!(
"Managed cloud tools are disabled because your OpenHuman AI credits are exhausted. Add credits or route the task to user-supplied providers."
);
}
}
Ok(())
}
/// POST JSON to a backend endpoint and parse the response `data` field.
pub async fn post<T: serde::de::DeserializeOwned>(
&self,
path: &str,
body: &serde_json::Value,
) -> anyhow::Result<T> {
self.request_json(reqwest::Method::POST, path, Some(body))
.await
}
/// GET from a backend endpoint and parse the response `data` field.View on GitHub (pinned to 7491200858)
Solutions
- Add OpenHuman AI credits (or raise the team budget cap) in the hosted account/billing UI, then retry after the budget probe cache TTL expires
- Route the task to user-supplied provider keys (BYOK) so the call bypasses the managed budget path entirely
- Confirm exhaustion first via the team usage RPC (hosted::team::get_usage) to distinguish real exhaustion from other failures
Example fix
// before — every managed call fails while credits are out
client.post("/agent-integrations/composio/execute", &body).await?;
// after — probe the budget gate first, fall back to a user-supplied provider
if let Some(cfg) = &budget_config {
if openhuman::hosted::team::managed_tool_budget_exhausted(cfg).await {
return run_with_user_supplied_provider(&body).await;
}
}
client.post("/agent-integrations/composio/execute", &body).await?; Defensive patterns
Strategy: fallback
Validate before calling
// Probe the budget gate before a managed call (same TTL-cached check the client uses)
use openhuman::hosted::team::managed_tool_budget_exhausted;
async fn managed_call_allowed(budget_config: &Option<Config>) -> bool {
match budget_config {
Some(cfg) => !managed_tool_budget_exhausted(cfg).await,
None => true, // no budget configured -> gate does not apply
}
} Try / catch
match client.post("/agent-integrations/composio/execute", &body).await {
Ok(resp) => Ok(resp),
Err(err) if err.to_string().contains("credits are exhausted") => {
// Budget state, not a bug: switch provider instead of retrying
run_with_user_supplied_provider(&body).await
}
Err(err) => Err(err),
} Prevention
- Surface remaining managed credits in the UI before they hit zero instead of letting agents discover exhaustion mid-task
- Cache the exhausted probe result yourself and short-circuit managed calls during the window instead of paying the error path
- Wire agent tool routing to fall back to user-supplied keys when the budget error appears — retrying the same managed path cannot succeed until credits are added
When it happens
Trigger: Any IntegrationClient.post/get/raw_delete to a /agent-integrations/* path (e.g. POST /agent-integrations/composio/execute, the Composio trigger endpoints) while team.get_usage reports the managed tool budget exhausted. Because the exhausted flag is TTL-cached, the error keeps firing for a short window even immediately after a top-up.
Common situations: Free/trial credits used up mid-task; a team budget cap reached while an agent loop hammers managed Composio tools; a stale cached exhausted flag from just before credits were refilled; shared team account drained by another member.
Related errors
AI-assisted analysis of tinyhumansai/openhuman@7491200858 (2026-08-17).
Data as JSON: /api/errors/68e02cd79de819c1.
Report an issue: GitHub.