diff --git a/docs/getting-started/quickstart.md b/docs/getting-started/quickstart.md index 9a7e308e56..98fd7c3d29 100644 --- a/docs/getting-started/quickstart.md +++ b/docs/getting-started/quickstart.md @@ -68,6 +68,76 @@ npm run eval -- assistant The command exits successfully after the agent calls the calculator and returns the expected answer. +## Add local delegation + +Keep using the same provider key and project. Add a specialist that identifies +the important facts: + +```ts +// agents/researcher.ts +import { agent } from "veryfront/agent"; + +export default agent({ + id: "researcher", + system: + "Identify the three most important facts in the user's request. Return concise bullet points.", + maxSteps: 3, +}); +``` + +Add a second specialist that turns notes into a clear answer: + +```ts +// agents/writer.ts +import { agent } from "veryfront/agent"; + +export default agent({ + id: "writer", + system: "Turn the supplied notes into a concise, practical answer.", + maxSteps: 3, +}); +``` + +Replace `agents/assistant.ts` with an orchestrator that can call both +specialists: + +```ts +// agents/assistant.ts +import { agent } from "veryfront/agent"; + +export default agent({ + id: "assistant", + name: "Assistant", + description: "Research a request and turn it into a practical answer.", + system: + "Use the researcher first. Pass the researcher's notes to the writer, then return the writer's answer.", + delegates: ["researcher", "writer"], + maxSteps: 10, +}); +``` + +Each delegate runs in the same Veryfront process as the assistant. The +`delegates` list exposes the specialists as `agent_researcher` and +`agent_writer` tools. It does not create hosted child runs or require a +Veryfront account. + +If the development server is still running, keep using it. If you stopped the +server for the eval, start it again: + +```bash +npm run dev +``` + +Open [http://localhost:3000](http://localhost:3000) and ask: + +```text +Compare two ways a small team could reduce support response time. Recommend one. +``` + +Confirm the run calls `agent_researcher` and `agent_writer`, then returns one +combined recommendation. For delegation controls and workflow-based +coordination, see [Multi-agent](../guides/multi-agent.md). + ## Next steps - [Use another inference provider](../guides/providers.md), including Anthropic, diff --git a/docs/guides/multi-agent.md b/docs/guides/multi-agent.md index 1340b62a93..e354c536e1 100644 --- a/docs/guides/multi-agent.md +++ b/docs/guides/multi-agent.md @@ -18,6 +18,12 @@ Each agent can omit `model` and use `openai/gpt-5.4-nano`, set `"auto"` for runt - At least two agents in `agents/` (see [Agents](./agents.md)). - A configured provider (see [Providers](./providers.md)). +Direct local delegation does not require a Veryfront account. Set a direct +provider key, run `veryfront dev`, and use `delegates` on the parent agent. The +runtime runs the delegates in-process and gives the parent one scoped tool for +each allowed agent. Veryfront Cloud is only required when you choose hosted run +or control-plane capabilities. + ## Agent-as-tool Convert an agent into a tool that another agent can call: diff --git a/docs/guides/self-hosting.md b/docs/guides/self-hosting.md index 8fd082c281..cc6a156a46 100644 --- a/docs/guides/self-hosting.md +++ b/docs/guides/self-hosting.md @@ -14,6 +14,27 @@ environment. Self-hosting does not require a Veryfront account. built-in local model. See [Providers](./providers.md). - A host that supports the current Node.js LTS, Deno, Bun, or containers. +## Check capability support + +Choose substitutes for managed capabilities before you deploy. + +| Capability | Self-hosted support | Requirement | +| ------------------------------------------ | --------------------------------------- | ----------------------------------------------------------------------------- | +| Pages, API routes, AG-UI, tools, and MCP | Supported | Run the project with `veryfront serve`. | +| Direct provider inference | Supported | Set the selected provider key or configure an OpenAI-compatible endpoint. | +| Local agent delegation with `delegates` | Supported | Delegates run in the application process. | +| Workflows | Supported | Use the in-memory backend or configure Redis for shared durable state. | +| Source-controlled project knowledge | Supported | Use the local project directory and the project knowledge tools. | +| Remote integration tools | Requires a backing API or service layer | Managed Salesforce and other remote tools have no standalone credential path. | +| Sandbox sessions | Requires a backing API or service layer | Configure authenticated sandbox session APIs. | +| Veryfront Cloud routing, storage, and runs | Requires Veryfront Cloud | These capabilities depend on project and control-plane context. | + +Remote integration definitions and execution are fetched from the configured +API layer. A provider model key does not make managed integration tools such as +`salesforce__*` available in a standalone project. Build a local tool against +the service API, or provide the backing service layer, until a standalone +credential path exists. + ## Build the project ```bash @@ -66,7 +87,16 @@ CMD ["npm", "start"] image builds the app. Copying the package files first also lets Docker reuse the dependency layer when only application code changes. -Build and run it: +Create `.env` with the runtime credentials. Do not commit this file: + +```dotenv title=".env" +OPENAI_API_KEY= +``` + +Replace `` with your OpenAI API key before you run the container or +Kubernetes commands. + +Build and run the image: ```bash docker build -t veryfront-app . @@ -76,6 +106,108 @@ docker run --rm -p 3000:3000 --env-file .env veryfront-app Set provider credentials and other secrets through the host environment. The `.dockerignore` keeps `.env` files out of the image. +## Deploy to Kubernetes + +Tag and push the image to a registry that your cluster can read: + +```bash +docker tag veryfront-app /veryfront-app: +docker push /veryfront-app: +``` + +Create a namespace and a Secret from the same uncommitted `.env` file: + +```bash +kubectl create namespace veryfront-app --dry-run=client -o yaml | kubectl apply -f - +kubectl create secret generic provider-credentials \ + --namespace veryfront-app \ + --from-env-file=.env \ + --dry-run=client -o yaml | kubectl apply -f - +``` + +Add `k8s.yaml`. Replace the image placeholder with the immutable tag you +pushed: + +```yaml title="k8s.yaml" +apiVersion: apps/v1 +kind: Deployment +metadata: + name: veryfront-app + namespace: veryfront-app +spec: + replicas: 1 + selector: + matchLabels: + app: veryfront-app + template: + metadata: + labels: + app: veryfront-app + spec: + containers: + - name: app + image: /veryfront-app: + ports: + - name: http + containerPort: 3000 + envFrom: + - secretRef: + name: provider-credentials + startupProbe: + tcpSocket: + port: http + periodSeconds: 5 + failureThreshold: 30 + readinessProbe: + tcpSocket: + port: http + initialDelaySeconds: 5 + periodSeconds: 5 + livenessProbe: + tcpSocket: + port: http + initialDelaySeconds: 15 + periodSeconds: 10 +--- +apiVersion: v1 +kind: Service +metadata: + name: veryfront-app + namespace: veryfront-app +spec: + selector: + app: veryfront-app + ports: + - name: http + port: 80 + targetPort: http +``` + +Apply the resources and wait for the Deployment: + +```bash +kubectl apply -f k8s.yaml +kubectl -n veryfront-app rollout status deployment/veryfront-app +``` + +When you change `.env`, rerun the Secret command above, then restart the +Deployment so new Pods read the updated values: + +```bash +kubectl -n veryfront-app rollout restart deployment/veryfront-app +kubectl -n veryfront-app rollout status deployment/veryfront-app +``` + +Open a local tunnel to the Service: + +```bash +kubectl -n veryfront-app port-forward service/veryfront-app 3000:80 +``` + +Open [http://localhost:3000](http://localhost:3000). Add an Ingress or service +load balancer according to your cluster platform after the local tunnel works. +Keep TLS and public access policy at that boundary. + ## Verify it worked Open [http://localhost:3000](http://localhost:3000) and send a message to the diff --git a/tests/docs/guide-content.test.ts b/tests/docs/guide-content.test.ts index 62ada29005..704c6d2da8 100644 --- a/tests/docs/guide-content.test.ts +++ b/tests/docs/guide-content.test.ts @@ -114,6 +114,31 @@ describe("guide content contracts", () => { ); }); + it("shows account-free local multi-agent delegation", async () => { + const quickstart = await Deno.readTextFile( + new URL("docs/getting-started/quickstart.md", repoRoot), + ); + const multiAgentGuide = await Deno.readTextFile( + new URL("docs/guides/multi-agent.md", repoRoot), + ); + + assertStringIncludes(quickstart, "## Add local delegation"); + assertStringIncludes(quickstart, "// agents/researcher.ts"); + assertStringIncludes(quickstart, "// agents/writer.ts"); + assertStringIncludes(quickstart, 'delegates: ["researcher", "writer"]'); + assertStringIncludes(quickstart, "`agent_researcher`"); + assertStringIncludes(quickstart, "`agent_writer`"); + assertStringIncludes(quickstart, "runs in the same Veryfront process"); + assertStringIncludes(quickstart, "If the development server is still running"); + assertEquals(quickstart.includes("tools: { invoke_agent: true }"), false); + + assertStringIncludes( + multiAgentGuide, + "Direct local delegation does not require a Veryfront account", + ); + assertStringIncludes(multiAgentGuide, "runs the delegates in-process"); + }); + it("keeps the Cloud quickstart on one gateway-to-deployment path", async () => { const quickstart = await Deno.readTextFile( new URL("docs/getting-started/cloud-quickstart.md", repoRoot), @@ -180,6 +205,34 @@ describe("guide content contracts", () => { assertEquals(guide.includes("veryfront deploy"), false); }); + it("documents self-hosting boundaries and a Kubernetes deployment", async () => { + const guide = await Deno.readTextFile( + new URL("docs/guides/self-hosting.md", repoRoot), + ); + + assertStringIncludes(guide, "## Check capability support"); + assertStringIncludes(guide, "Direct provider inference"); + assertStringIncludes(guide, "Local agent delegation with `delegates`"); + assertStringIncludes(guide, "Remote integration tools"); + assertStringIncludes(guide, "Requires a backing API or service layer"); + assertStringIncludes(guide, "## Deploy to Kubernetes"); + assertStringIncludes(guide, "kubectl create namespace veryfront-app"); + assertStringIncludes(guide, "kubectl create secret generic provider-credentials"); + assertStringIncludes(guide, "--from-env-file=.env"); + assertStringIncludes(guide, "--dry-run=client -o yaml | kubectl apply -f -"); + assertStringIncludes(guide, "Replace ``"); + assertStringIncludes(guide, "apiVersion: apps/v1"); + assertStringIncludes(guide, "kind: Deployment"); + assertStringIncludes(guide, "startupProbe:"); + assertStringIncludes(guide, "tcpSocket:"); + assertStringIncludes(guide, "kubectl apply -f k8s.yaml"); + assertStringIncludes(guide, "rollout restart deployment/veryfront-app"); + assertStringIncludes( + guide, + "kubectl -n veryfront-app port-forward service/veryfront-app 3000:80", + ); + }); + it("documents the current knowledge ingest JSON result shape", async () => { const guide = await Deno.readTextFile( "docs/guides/cli-knowledge-ingestion.md", diff --git a/tests/docs/guide-contracts.test.ts b/tests/docs/guide-contracts.test.ts index 8b899d3899..b882149ee5 100644 --- a/tests/docs/guide-contracts.test.ts +++ b/tests/docs/guide-contracts.test.ts @@ -232,6 +232,7 @@ const GUIDE_CONTRACTS: Record = { "getting-started/quickstart.md": { references: [ "../guides/providers.md", + "../guides/multi-agent.md", "./create-project.md", "../api-reference/veryfront/agent.md", "../api-reference/veryfront/tool.md", @@ -246,6 +247,9 @@ const GUIDE_CONTRACTS: Record = { "calculator.ts", "What is 128 divided by 8?", "Inference OpenAI direct", + 'delegates: ["researcher", "writer"]', + "agent_researcher", + "agent_writer", ], }, "getting-started/cloud-quickstart.md": { @@ -318,6 +322,13 @@ const GUIDE_CONTRACTS: Record = { "veryfront serve", "ship the whole project directory, not just `dist/`", "Dockerfile", + "Check capability support", + "Remote integration tools", + "Deploy to Kubernetes", + "--from-env-file=.env", + "startupProbe:", + "rollout restart deployment/veryfront-app", + "kubectl apply -f k8s.yaml", ], }, "guides/deploy-from-ci.md": { @@ -675,7 +686,12 @@ const GUIDE_CONTRACTS: Record = { "../api-reference/veryfront/agent.md", "../api-reference/veryfront/workflow.md", ], - snippets: ["agentAsTool", "getAgentsAsTools", "workflow"], + snippets: [ + "Direct local delegation does not require a Veryfront account", + "agentAsTool", + "getAgentsAsTools", + "workflow", + ], }, "guides/oauth.md": { references: ["../api-reference/veryfront/oauth.md"],