environments: Set it up once. Every run starts ready.

A ConvOps environment bundles what an agent run needs: repositories, git access, secrets, MCP servers, allowed tools and a commit identity. A check proves it works before any run.

secrets by one-time link · masked in every log · checked before any run

parts
  • web-apprepository
  • deploy keygit access
  • STRIPE_KEYsecret
  • githubMCP server
  • tasks, memoryConvOps tools
  • release-botcommit identity
environment · examplerelease-bot environment
draft
  • repositoryweb-app
  • git accessdeploy key
  • secretSTRIPE_KEY
  • MCP servergithub
  • ConvOps toolstasks, memory
  • commit identityrelease-bot
  • secrets resolve
  • repositories clone
  • variables arrive
  • nothing pushed
in short

How do you set up a secure environment for AI agent runs?

Define it once in ConvOps: the repositories, the secrets, the MCP servers and which of their tools a run may use. Every run then starts from the same checked setup.

ConvOps is the operations layer for AI agents: an MCP server that holds your team's process as workflows, with approval gates, a shared memory and an audit trail. It runs no AI models.

key facts · october 2026

  • Secret values are posted through a one-time link, never pasted into chat. No ConvOps tool or API returns a value, and values are masked in every log and transcript.
  • Git access maps an address prefix to a deploy key or token; the longest matching prefix supplies the credential.
  • Each MCP server attached to an environment has allow and deny rules, so a run is offered only the tools those rules let through.
  • The environment check prepares everything in a throwaway copy, reports each item as ready or failed with the reason, and never pushes.

best for

  • Unattended runs that need repositories, keys and MCP servers without a person at a laptop.
  • Security reviewers who want to see exactly what an agent can touch before it runs.

not for

  • A general secrets manager for your applications.

updated

the problem

Works on my machine, now for agents.

Agents need repositories, keys and tools. Without a shared setup, each of those lives somewhere nobody governs.

“Where did that token come from?”

Someone pasted it into a chat. Now it sits in a transcript, a log and a model's context.

“What happens when someone leaves?”

Repo access, keys and config lived on one laptop. The agent stops working the day they do.

“Why could the agent delete issues?”

It got every tool the server offers, because nobody decided which ones it should have.

watch it come together

One environment, set up once.

A release bot gets its repository, a secret, a tool server and its tools. Then a check proves it, before any real work.

01you, once

Add the repository.

Name web-app and add a deploy key for it. When several git access rules match an address, the most specific one supplies the credential.

environment · release-botexample
repositorygitlab.com/acme/web-appfolder .

git access · which credential clones it?

  • gitlab.com/acmetoken
  • gitlab.com/acme/web-appdeploy key

longest matching prefix wins · one rule covers https, ssh and git@

02a teammate

Send the secret through a link.

ConvOps issues a one-time link. A teammate posts the value there. It never enters a chat, and it is never shown again.

secret · one-time linkexample
STRIPE_KEYunset
teammate posts the value
••••••••••••••post

value posted once, never shown again

03you, once

Run a tool server beside the agent.

The GitHub MCP server starts as a sidecar inside each run pod. Two of its tools are denied, so the run never sees them.

run pod · example
agentgithub MCP · sidecar
environment · MCP serversexample
githubsidecar in the run pod
offered to the run: 0 MCP tools
04you decide

Decide which ConvOps tools it gets.

Tasks and memory on. Secrets and schedules off. A person picks the list, and the run is offered exactly that.

environment · ConvOps toolsyou decide
offered to the run: 0 ConvOps tool groups

task tools reach the run's own task · widening one saves with a warning

05ConvOps

Check it before any run.

The environment check clones every repository, resolves every secret and probes every variable in a throwaway copy. Nothing is pushed.

environment checkthrowaway copy
06every run

Every run starts ready.

Make it the project default. Each run starts in its own pod with repositories cloned, secrets in place and only the allowed tools.

project · web-appexample
default environmentrelease-botchecked
  • run 7f3aFix refund roundingrepos clonedsecrets in placeallowed toolsready
  • run 8c1eRetry payments on 409repos clonedsecrets in placeallowed toolsready
  • run 92b0Bump Stripe SDKrepos clonedsecrets in placeallowed toolsready
environment · release-botexample
repositorygitlab.com/acme/web-appfolder .

git access · which credential clones it?

  • gitlab.com/acmetoken
  • gitlab.com/acme/web-appdeploy key

longest matching prefix wins · one rule covers https, ssh and git@

secrets

Posted once. Masked everywhere.

A one-time link takes the value. Each run gets it in its own secret. Logs and transcripts show a lock, never the value.

run 8c1e · agentexample
secret · one-time linkexample
STRIPE_KEYunset
teammate posts the value
••••••••••••••post

value posted once, never shown again

the boundary

A person decides what the agent touches.

Allow or deny each MCP tool. Switch ConvOps tools on or off. A run is offered that list and nothing else.

environment · MCP serversexample
githubsidecar in the run pod
sentryremote
environment · ConvOps toolsyou decide

a tool that reaches beyond the run's own task saves with a warning naming what a run can then do

offered to the run: 0 MCP tools · 0 ConvOps tool groups tap any row to change it
environment check

Proven before the first run.

The check clones, resolves and probes in a throwaway copy. A failure names its reason. Fix it, check again, then put it to work.

parts
  • web-apprepository
  • deploy keygit access
  • STRIPE_KEYsecret
  • githubMCP server
  • tasks, memoryConvOps tools
  • release-botcommit identity
environment check · examplerelease-bot environment
draft
  • repositoryweb-app
  • git accessdeploy key
  • secretSTRIPE_KEY
  • MCP servergithub
  • ConvOps toolstasks, memory
  • commit identityrelease-bot
  • secrets resolve
  • repositories clone
  • variables arrive
  • nothing pushed

example failure clone gitlab.com/acme/web-app · no git access for this address →add a deploy key, check again

what an environment holds

Five parts. One setup.

Repositories

Cloned into folders of the working copy. Git access maps an address to a deploy key or token.

longest prefix wins

Secrets

Posted once through a one-time link. Never pasted in chat, never returned, masked in every log.

one-time link

MCP servers

Remote, or a container sidecar inside the run pod. Each tool allowed or denied.

per-tool rules

ConvOps tools

A person switches each tool on or off. Task tools reach the run's own task by default.

you decide

Commit identity

Every commit a run makes carries the name and email you set, as author and committer.

traceable work

the difference

Ad-hoc setups vs environments.

  • Tokens pasted into chats and prompts.
  • Repo access set up on one laptop.
  • The agent gets every tool a server offers.
  • Commits land under whoever ran it.
  • You find out it is broken mid-run.
  • The setup leaves when the person leaves.

An environment is one call

Repositories in order (exactly one receives the work), plain variables, secret refs, MCP servers with tool rules, ConvOps tools and a commit identity. Values are never accepted.

payload
// agent_environments_manage · example
{
  "action": "create",
  "name": "release-bot",
  "entries": [
    { "repository_id": "web-app", "folder": ".", "receives_work": true },
    { "repository_id": "design-tokens", "folder": "vendor/tokens", "shallow": true }
  ],
  "variables": [{ "name": "NODE_ENV", "value": "test" }],
  "secrets": [
    { "name": "STRIPE_KEY", "secret": { "source": "intake" } },
    { "name": "SENTRY_TOKEN", "secret_ref_id": "sr_4b81" }
  ],
  "mcp_servers": [
    { "server": "github",
      "rules": { "default": "allow",
                 "deny": ["delete_*", "merge_pull_request"] } }
  ],
  "convops_tools": ["tasks_get", "task_notes_add",
                    "workflow_advance", "memory_recall", "memory_store"],
  "git_identity": { "name": "release-bot", "email": "release-bot@example.com" }
}
agent_environments_manage · create

A new secret returns a link

Every secret added with source "intake" comes back as a one-time link for a person to post the value. The ref stays unset until then.

payload
// result (excerpt) · example
{
  "intake": [{
    "name": "STRIPE_KEY",
    "url": "https://app.example.com/intake/…",
    "command": "curl -X POST … --data-binary @-",
    "expires_at": "2026-10-03T18:00:00Z"
  }]
}
create result · intake

Git access by address prefix

One prefix covers https, ssh and git@ forms and matches whole path segments. The most specific prefix supplies the credential.

payload
// git_access_manage · example
{ "action": "create", "prefix": "gitlab.com/acme",
  "kind": "token", "username": "oauth2",
  "secret": { "source": "intake" } }

{ "action": "create", "prefix": "gitlab.com/acme/web-app",
  "kind": "ssh_key",
  "secret": { "source": "intake" } }

// cloning gitlab.com/acme/web-app uses the deploy key:
// the longest matching prefix wins
git_access_manage · create

An MCP server as a sidecar

A container server starts beside the agent in the run pod and is reached on localhost. Credentials go in secret env, never in the address.

payload
// mcp_servers_manage · example
{
  "action": "create",
  "name": "github",
  "transport": "container",
  "image": "ghcr.io/example/github-mcp:1.4.2",
  "port": 8080,
  "env": [{ "name": "GITHUB_TOKEN", "secret": { "source": "intake" } }],
  "rules": { "default": "allow", "deny": ["delete_*"] }
}
// started beside the agent in the run pod,
// reached on http://127.0.0.1:8080/mcp
mcp_servers_manage · create

The check, as a result

Each repository ready or failed with a reason, each variable present or empty. Secret values are never echoed. Nothing is pushed.

payload
// environment_checks_submit · result · example
{
  "status": "succeeded",
  "terminal": true,
  "output": {
    "repositories": [
      { "folder": ".", "address": "gitlab.com/acme/web-app",
        "ref": "main", "head": "9f2c1e7", "status": "ready" },
      { "folder": "vendor/tokens", "address": "gitlab.com/acme/design-tokens",
        "ref": "main", "head": "41ab0d3", "status": "ready" }
    ],
    "variables": [
      { "name": "NODE_ENV", "kind": "plain", "status": "present", "value": "test" },
      { "name": "STRIPE_KEY", "kind": "secret", "status": "present" },
      { "name": "SENTRY_TOKEN", "kind": "secret", "status": "present" }
    ]
  }
}
environment_checks_submit
questions

What security reviewers ask.

Where are secret values kept, and who can read them?

A value is posted through a one-time link, or set by a signed-in person in the app. No ConvOps tool or API returns it. A run receives it in its own per-run Secret, and it is masked in every log and transcript. Self-hosted, a secret can also name a Kubernetes Secret in your runs namespace, which the run pod reads directly.

Can an agent ask for a secret in chat?

No tool accepts a value. When a secret is added, ConvOps returns a one-time link for a person to post it, so the value never passes through a conversation. Values must be at least 8 characters.

How does git access work across many repositories?

Git access maps an address prefix to a deploy key or token. When a repository is cloned, the longest matching prefix supplies the credential, so one token can cover an organisation and one deploy key can override it for a single repository.

Can I limit which MCP tools a run can use?

Yes. Each MCP server attached to an environment has rules: a default of allow or deny, then deny patterns, then allow patterns. A run is offered only the tools those rules let through. Servers can be remote, or run as container sidecars inside the run pod.

Which ConvOps tools can a run call?

The ones the environment switches on. Task tools reach only the run's own task unless you widen them. Granting a tool that reaches further, such as secrets or schedules, saves with a warning that names what a run can then do.

What does the environment check actually do?

It prepares the environment in a throwaway copy: resolves every secret, clones every repository, probes that each variable arrives, reports each one as ready or failed with the reason, then removes the copy. It never pushes.

Whose name is on the commits?

The commit identity set on the environment, as author and committer. Without one, the workspace default applies. Work is pushed to a task branch for review, or straight to the ref when you configure it.