Skip to content

Hosted Hermes Agents

Copy page

A hosted Hermes agent is a NousResearch Hermes instance that Divinci runs for you in its own isolated Cloudflare Sandbox container — one container per agent, addressed by a stable per-agent key. You get a tool-using, self-improving agent without operating a server, and divinci.hermesAgents is how you manage the fleet.

Each agent has:

  • a model — a Divinci-paid platform model or a bring-your-own-key model,
  • an optional persona (system prompt) applied to every turn,
  • an optional linked Release whose knowledge base grounds every turn (RAG),
  • an hsk- proxy key that lets any OpenAI-compatible client drive it.

Platform models are hosted and paid for by Divinci — no provider key needed:

| Model id | Notes | | --- | --- | | vertex_ai/gemini-2.5-flash | Default. Fast, tool-capable Gemini on Vertex AI. | | vertex_ai/gemini-2.5-pro | Most capable Gemini. | | cloudflare/@cf/meta/llama-3.3-70b-instruct-fp8-fast | Open-weight Llama on Cloudflare Workers AI. |

Or bring your own key for openai, anthropic, openrouter, or gemini (Google AI Studio) with any <provider>/<model> id — e.g. anthropic/claude-sonnet-4-5. BYOK keys are field-encrypted at rest and never returned by the API: reads expose only the provider name and a hasProviderApiKey boolean.

// Platform model — works immediately, no key required
const agent = await divinci.hermesAgents.create("ws_123", {
title: "Support Bot",
hermesModel: "vertex_ai/gemini-2.5-flash",
systemPrompt: "You are a concise, friendly support agent.",
});
console.log(agent._id); // agent id for the management API
console.log(agent.proxyApiKey); // hsk-… — for OpenAI-compatible clients
// BYOK — provider spend lands on your own account
const byok = await divinci.hermesAgents.create("ws_123", {
title: "Claude Agent",
hermesModel: "anthropic/claude-sonnet-4-5",
provider: "anthropic",
providerApiKey: process.env.ANTHROPIC_API_KEY!, // encrypted at rest
});

Creation is lazy — no container spins until the first chat, so an unused agent costs nothing. There is a per-workspace cap on agents (default 10).

Link a Release and every turn retrieves relevant context from that Release's knowledge base before the model answers. The agent keeps its own model and persona — the Release contributes only grounding content.

const grounded = await divinci.hermesAgents.create("ws_123", {
title: "Docs-Grounded Agent",
releaseId: "rel_abc123", // 24-hex release id in the same workspace
});
// Link, swap, or unlink later:
await divinci.hermesAgents.update("ws_123", grounded._id, { releaseId: "rel_def456" });
await divinci.hermesAgents.update("ws_123", grounded._id, { releaseId: "" }); // unlink
const reply = await divinci.hermesAgents.chat("ws_123", agent._id, [
{ role: "user", content: "Summarize our refund policy." },
]);
console.log(reply.choices?.[0]?.message?.content);

The response is OpenAI-compatible. Each successful turn is metered as a small flat fee to the workspace wallet, escrowed before dispatch and refunded on any failure — you pay per successful turn.

const agents = await divinci.hermesAgents.list("ws_123");
const one = await divinci.hermesAgents.get("ws_123", agent._id);
// one.status: "provisioned" (never booted) | "active" | "stopped" (idle-reaped)
await divinci.hermesAgents.update("ws_123", agent._id, {
hermesModel: "vertex_ai/gemini-2.5-pro",
enabled: false, // disabled agents reject chat with 403
});
await divinci.hermesAgents.delete("ws_123", agent._id); // stops the container too

Idle containers auto-sleep after ~30 minutes and long-idle agents are marked stopped by a background sweep. Both are non-destructive — the next chat re-provisions transparently.

The proxyApiKey (hsk-…) works with any OpenAI-compatible client — including a locally-installed Hermes — via the per-agent proxy:

Terminal window
export OPENAI_BASE_URL="https://api.divinci.app/api/v1/hermes-proxy"
export OPENAI_API_KEY="hsk-your-agent-proxy-key"

The proxy resolves the agent from the key, server-side — there is no header or path a caller can set to reach a different tenant's container. Rotate the key to revoke all clients holding the old one:

const rotated = await divinci.hermesAgents.regenerateKey("ws_123", agent._id);
console.log(rotated.proxyApiKey); // new hsk-…; the old key is dead

An agent can wake on a schedule, decide whether it has anything worth saying, and either record the result or deliver it. shadow runs the full metered turn and writes a run row without posting; live also posts to the Slack home channel. It defaults to shadow, so enabling the feature can never by itself put a message in a customer's channel.

await divinci.hermesAgents.update("ws_123", agent._id, {
proactive: {
enabled: true,
mode: "shadow",
schedule: { hour: 9, minute: 0, timezone: "America/Los_Angeles" },
intervalHours: 3, // wake every 3 hours; null ⇒ once a day
goals: ["Watch the nightly E2E run and flag new failures"],
memories: ["The integration branch is `preview`, not `main`."],
deliver: { slack: true },
},
});
// What has it been saying?
const { runs } = await divinci.hermesAgents.proactiveRuns("ws_123", agent._id, 10);

| Field | Meaning | |-------|---------| | enabled | Master switch. false by default. | | mode | shadow (record only) or live (also deliver). Defaults to shadow. | | schedule | { hour, minute, timezone } in the agent's own IANA zone. With intervalHours, this anchors the first wake. | | intervalHours | Wake every N hours (1-24). null ⇒ once a day. | | goals / memories | Admin-authored text, max 50 entries each. | | deliver | { slack?, email?, sms? }. Merged as a whole, not field-by-field. | | clear | Send proactive: null to remove the config entirely. |

lastRunAt is server-managed and deliberately not writable: a client able to rewind it could make an agent due again immediately, which is the one field that turns a config edit into unbounded spend on the owner's wallet.