npx skills add ...
npx skills add veris-ai/veris-skills --skill agent-integration
Integrate a raw customer agent repo with Veris end to end. Installs or verifies veris-cli, logs in, creates or reuses a Veris environment, analyzes the repo, generates or updates `.veris/veris.yaml`, `.veris/Dockerfile.sandbox`, `.veris/.dockerignore`, configures runtime env vars, and can finish with `veris env push`. Use when a repo has no Veris setup yet, or when an existing `.veris/` integration is stale and needs to be refreshed.
npx skills add veris-ai/veris-skills --skill agent-integration
Integrate this agent repo with Veris from scratch.
This skill takes a repo from "plain customer agent source" to "Veris-ready and pushable." If the user provided a path to an agent repo, use that as the repo root. Otherwise use the current working directory.
Treat any existing .veris/ files or old scaffold output as starting material only. Use the current bundled references in this skill as the source of truth for what you generate.
Veris exists to test an agent under realistic conditions. The agent is the thing being tested; Veris is the harness around it. That asymmetry drives every decision in this skill:
.veris/. .veris/veris.yaml, .veris/Dockerfile.sandbox, .veris/config.yaml, .veris/.dockerignore are the deployment descriptor — the equivalent of a Helm chart or docker-compose.yaml for this agent. They describe how to stand the agent up for this environment. They do not contain behavior that belongs inside the agent..veris/ file that is not pure config is a container-orchestration start.sh for bundling multiple processes (e.g., a database alongside the agent). Even that starts and runs the agent as-shipped; it does not transform its behavior.When in doubt: the agent's author should be able to read .veris/ and recognize it as "the deploy config for Veris," not as "someone forked and patched my agent."
A transport bridge translates between the actor's channel format (e.g. voice_ws PCM16) and the agent framework's native transport (e.g. LiveKit WebRTC, SIP media, a proprietary message envelope) while preserving the underlying payload byte-for-byte. It is not a wrapper. The same shape exists in production for the agent's other product surfaces — mobile clients, kiosks, IVR vendors — so the bridge is genuine product code, not Veris-specific glue.
A bridge is allowed when:
app/bridge.py), exercised by the agent's own tests — not in .veris/. It is the agent's voice_ws-on-WebRTC product surface; Veris is just one caller.A bridge is not allowed when:
RawAudioFrameSerializer for voice_ws, the framework's own HTTP plugin for http, etc.). Configure the framework first; bridge only if the transport is fixed.Quick rubric: "same bytes, different network format" = transport bridge (allowed). "Different bytes / different shape" = wrapper (not allowed).
See reference/infrastructure-patterns.md Pattern 9 for the architecture and reference/voice-channels.md for the voice-specific application.
This is the one exception that genuinely breaks the "no Veris-specific code path" rule — and it is deliberate. It applies only to voice agents built on hosted speech-to-speech platforms (ElevenLabs Conversational AI, OpenAI Realtime, Gemini Live, Vapi, and the like) whose tools execute inside the agent process — as client tools that round-trip on the vendor's WebSocket, or as Vapi-style server tools the platform POSTs back to the agent's webhook over HTTP. Either way the call never reaches the spoken transcript.
Why it's needed: the voice grader builds its trace from the spoken transcript plus any tool-call events the agent reports. A client tool never reaches the transcript, so without a report the grader can't see the tool ran and false-flags real actions (a card freeze, a replacement) as hallucinations. Text/HTTP agents don't have this problem — their tool calls are captured automatically — so this exception is voice-only.
The fix: after each tool runs, the agent POSTs an agent_tool_call event to the sandbox engine, and the platform renders it into the graded trace. Keep it strictly minimal so it stays instrumentation, not a wrapper:
SIMULATION_ID (unset in production → return immediately). Production behavior is unchanged.This is sanctioned only for client-tool grader visibility, only for voice agents, and only in this minimal shape — it is not a license for general shims. The exact endpoint, event schema, and a copy-paste hook are in reference/voice-channels.md.
.env.simulation. The current runtime flow is agent.environment plus veris env vars set.actor.channels schema and canonical service names. Do not generate legacy persona.modality, email_address, or old service aliases unless the user explicitly asks for compatibility.veris-cliveris loginveris env createveris env vars setveris env pushIf the user says "go all the way", "do everything", or otherwise pre-approves the full flow:
veris env create, veris env push, veris env vars set with real secretsvoice_ws channel, framework choice, trailing silence, reporting client-tool calls so the grader can see them): reference/voice-channels.mdveris.yaml structure: reference/veris-yaml-schema.md| Phase | Goal |
|---|---|
| 0 | Bootstrap Veris tooling and environment |
| 1 | Discover the repo and current runtime |
| 2 | Analyze dependencies and service strategy |
| 3 | Choose integration mode and container architecture |
| 4 | Generate .veris/veris.yaml |
| 5 | Generate .veris/Dockerfile.sandbox and supporting files |
| 6 | Configure runtime env vars, validate, and push |
| 7 | Smoke-validate with a single scenario + simulation |
[Phase 0/7]
Tell the user: "I'm going to make sure this repo has the Veris tooling and environment wiring needed for the rest of the integration work."
Confirm the directory is an agent repo, not just a parent folder. Look for source code, dependency manifests, and app entrypoints.
veris-cliCheck whether veris is installed and working.
If not installed:
uv tool install veris-clipip install veris-cliExplain which install path you are using and why.
Check whether the user is already logged in and which profile/backend they are using.
If not authenticated:
veris login for browser authDo not proceed to veris env push until auth is working.
.veris/Inspect:
.veris/config.yaml.veris/veris.yaml.veris/Dockerfile.sandbox.veris/.dockerignoreIf .veris/ does not exist, or it exists but has no environment binding:
veris env create --self-serve --name "<name>".--self-serve (veris-cli >= 2.27.0) is the right mode for this skill's audience: you are authoring .veris/ yourself, and the env should be ready for veris env push immediately. Without it, env create defaults to managed-setup mode where the Veris team generates Dockerfile.sandbox + veris.yaml for the customer, and veris env push returns 409: Run veris env submit first until that setup completes. If veris env create --help doesn't list --self-serve, bump the CLI first using the install manager that owns veris (uv tool upgrade veris-cli or pip install -U veris-cli). For recovery from an env that was already created without --self-serve, see phases/troubleshooting.md.
Explain what veris env create gives them:
.veris/veris.yaml — Veris simulation config.veris/Dockerfile.sandbox — image build definition.veris/.dockerignore — build-context exclusions.veris/config.yaml — environment binding for this repoThe generated .veris/ files are just a starting point. They may use old defaults or generic placeholders. You are responsible for replacing them with the correct integration for this repo.
Proceed directly to Phase 1.
[Phase 1/7]
Tell the user: "I'm going to inventory how this repo currently runs, what it depends on, and how users interact with it."
If .veris/ already exists, read all existing Veris files first. Call out anything that looks stale or legacy:
persona.modalityemail_addresscrm, calendar, oracle.veris/config.yaml env bindingRead and summarize any of:
docker-compose.yml, docker-compose.yaml, compose.ymlDockerfile, Dockerfile.*Procfilesupervisord.conf, supervisord.inivercel.json, serverless.yml, netlify.tomlIdentify:
Read:
.env.example, .env.sample, .env.templateCollect every env var the agent reads, and note which are:
Read the package manifests for the repo’s language/runtime and identify:
Find the actual code path that handles incoming user work:
If the repo has no traditional application entrypoint — no main.py, app.py, server.js, index.ts — check whether it is a platform-hosted agent: a repo of config files that runs on an installed framework (CrewAI, LangServe, AutoGen, Dify, n8n, Flowise, or similar).
Signs:
pyproject.toml or package.json lists a framework as the main dependencyIf this is the case:
reference/infrastructure-patterns.md for the full restructuring approachpip install . on these reposThis is critical. Determine how the simulated actor should talk to the agent.
Look for four classes of interfaces:
HTTP
WebSocket
Function
handle_message-style functions the agent's own documentation treats as an entry pointDo not invent a function interface by wrapping a CLI or a server. If the agent is CLI-only in production, the integration is CLI-driven — surface that and find the right Veris channel for it, or log it as a platform gap. A function channel is only correct when the repo already ships a callable as its primary or documented interface.
If both network and function modes are viable, use the repo's real product interface. That is what runs in production; that is what we test.
Tell the user exactly what you found and confirm the likely best integration path before continuing.
Proceed to Phase 2.
[Phase 2/7]
Tell the user: "I'm now classifying each dependency into mock, bundle, external, or skip."
Read:
For every dependency, classify it as one of:
Postgres
postgres or an external DBpostgres, find the schema artifact or migration source and determine the best copy pathLLM providers
Auth helpers
Web search and scraping
Real internet egress (general)
Walk through your dependency analysis with the user before moving on. The user should understand:
Wait for approval before proceeding.
[Phase 3/7]
Tell the user: "I'm locking down how this agent will run inside the Veris container and how the actor will talk to it."
Read reference/infrastructure-patterns.md.
Pick one of:
If you choose a function channel:
agent.entry_point and agent.port in veris.yamlactor.config.MAX_TURNS: 1If you choose HTTP / WS / email:
start.sh is needed for bundled infra or multiple processesDetermine:
/agentstart.sh is required to bundle multiple processes (this is container orchestration, not agent modification)Do not plan "which code changes are necessary." The target is zero code changes to the agent. If an env-var override isn't enough and the agent genuinely can't run as-shipped, that's a finding — escalate it rather than patching the source.
Explain:
If you believe any agent-side code change is needed, flag it here and stop. The default answer is zero code changes. If you can't see a way forward without one, it's probably a Veris platform gap, not an integration step.
The single pre-sanctioned exception: a client-tool voice agent (ElevenLabs Conversational AI, OpenAI Realtime, Gemini Live, …) needs the agent_tool_call reporting hook so the grader can see its tools — see the Core framing exception and reference/voice-channels.md. That one is expected; add it without escalating. Everything else still stops here.
Wait for approval before proceeding.
.veris/veris.yaml[Phase 4/7]
Tell the user: "I'm generating the final Veris configuration in the current preferred schema."
Read:
actor.channels, not persona.modalityreference/service-mapping.mdagent_inbox, not email_addressactor.config.MAX_TURNS when there is a concrete reason, usually a one-shot function integration*_INTERVAL knobs unless the user explicitly asks for advanced tuningveris.yamlagent.environment${VAR} in agent.environment when you need expansion/composition; if the agent can read a runtime env var directly, prefer setting it with veris env vars setHTTP / WS / Email
agent.code_pathagent.entry_pointagent.portFunction
agent.code_pathagent.entry_pointagent.portactor.channels[0].type: functioncallable: ...Show the complete veris.yaml, explain the sections, and get approval before writing or finalizing it.
.veris/Dockerfile.sandbox And Supporting Files[Phase 5/7]
Tell the user: "I'm generating the image build and any small support files needed for this integration."
Read:
WORKDIR /appveris.yaml into the imageuv, and Node.jsCreate only what is needed:
start.sh for bundling multiple processes (e.g., a database alongside the agent) — this is container orchestration, same as a docker-compose.yaml would be.veris/.dockerignore updates if the repo has large directories the default ignore file missesDo not create Python "wrapper modules" that expose the agent as a callable, translate Veris actor calls into the agent's native format, or otherwise insert themselves between the actor and the agent. Use the agent's real interface.
The agent runs in Veris exactly as it runs in production. That means:
If you find yourself wanting to change the agent's source, stop. Either:
agent.environment or veris env vars set), orUnrelated refactors are obviously out.
The one sanctioned source addition is the client-tool reporting hook for voice agents (see the Core framing exception). It is the deliberate exception to "no code changes," not a counterexample to it: it's a no-op outside a simulation, it never alters the agent's behavior, and it exists solely so the grader can see client tools that otherwise never reach the trace. Add it for client-tool voice agents; don't generalize it into other source edits.
Proceed directly to Phase 6 once the files are in place.
[Phase 6/7]
Tell the user: "I'm turning this into a pushable Veris environment."
Read:
Classify env vars into:
agent.environmentveris env vars set.env or shell exports for local smoke testsDo not create .env.simulation.
Generate the exact veris env vars set commands the user needs.
If the user provides actual values and wants you to do it, run the commands for them.
Shell interpolation pitfall: when running veris env vars set KEY="$VAR" --secret with a shell variable, verify the source variable is actually set first (printenv VAR or test -n "$VAR"). An empty or unset variable expands to "" silently — the CLI will happily save an empty secret with no error, and the agent will fail at runtime with a confusing auth/provider error instead of a clear "missing key" message.
Before pushing, verify:
veris is installed.veris/config.yaml has an environment ID.veris/veris.yaml exists.veris/Dockerfile.sandbox existsOptional but encouraged:
docker build -f .veris/Dockerfile.sandbox . smoke test when that is likely to catch obvious breakage quicklyIf the user approves, run:
Or with an explicit tag if the user wants one:
If the push fails:
Summarize:
veris env push succeeded and which tag was createdThen suggest the next commands:
veris scenarios createveris simulations create[Phase 7/7]
Tell the user: "I'm going to run a single scenario and simulation to verify the integration works end-to-end."
The goal is a single short interaction that exercises the agent's primary interface.
Wait for it to complete.
Review the simulation for:
If the smoke test fails:
actor.channels request/response mapping matches the actual API shapeIf the smoke test passes, summarize:
Then suggest full scenario generation (veris scenarios create --num N) and simulation as the next step.
If veris env create scaffolds old-looking placeholders, overwrite them with the current preferred shape from this skill.
Use a function channel only when the agent already exposes a callable as part of its public interface. Do not force a networked product into a function callable just because it seems simpler, and never create a wrapper file to invent a callable the agent doesn't already have.
If the integrated agent is clearly one-shot/stateless, carry that through explicitly by setting actor.config.MAX_TURNS: 1.
If login, secrets, or env-var values still require user action, say so plainly. The goal is to get as far as possible, not to hide blockers.
veris scenarios create --num 1veris simulations create --scenario-set-id <id>