Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions docs/getting-started/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
6 changes: 6 additions & 0 deletions docs/guides/multi-agent.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
134 changes: 133 additions & 1 deletion docs/guides/self-hosting.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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=<API_KEY>
```

Replace `<API_KEY>` with your OpenAI API key before you run the container or
Kubernetes commands.

Build and run the image:
Comment thread
coderabbitai[bot] marked this conversation as resolved.

```bash
docker build -t veryfront-app .
Expand All @@ -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 <REGISTRY>/veryfront-app:<TAG>
docker push <REGISTRY>/veryfront-app:<TAG>
```

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 -
```
Comment thread
coderabbitai[bot] marked this conversation as resolved.

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: <REGISTRY>/veryfront-app:<TAG>
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
Expand Down
53 changes: 53 additions & 0 deletions tests/docs/guide-content.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down Expand Up @@ -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 `<API_KEY>`");
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",
Expand Down
18 changes: 17 additions & 1 deletion tests/docs/guide-contracts.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@ const GUIDE_CONTRACTS: Record<string, GuideContract> = {
"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",
Expand All @@ -246,6 +247,9 @@ const GUIDE_CONTRACTS: Record<string, GuideContract> = {
"calculator.ts",
"What is 128 divided by 8?",
"Inference OpenAI direct",
'delegates: ["researcher", "writer"]',
"agent_researcher",
"agent_writer",
],
},
"getting-started/cloud-quickstart.md": {
Expand Down Expand Up @@ -318,6 +322,13 @@ const GUIDE_CONTRACTS: Record<string, GuideContract> = {
"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": {
Expand Down Expand Up @@ -675,7 +686,12 @@ const GUIDE_CONTRACTS: Record<string, GuideContract> = {
"../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"],
Expand Down