Proposals
A proposal is a source change waiting for review. It comes from one of three places:
- A deployed agent suggests a change to its own source after someone asks it in chat, such as "from now on, confirm before refunding". The agent cannot change itself.
- The builder chat in Studio suggests a change to any source file for the person building the agent.
- A fix drafted from an issue. It shows "Fix for issue" with a link to the issue.
Each proposal waits on the Proposals page in Studio until a person approves or discards it, and approving it commits the change and deploys it.
Turn it on
The propose_source_change tool is available to agents deployed on Amodal, in web chat and API chat. It is not registered under amodal dev or in channel sessions such as Slack.
Declare it beside list_repo_files, which the agent uses to see which files exist, and read_repo_file, which it uses to read a file before replacing it:
{ "tools": ["list_repo_files", "read_repo_file", "propose_source_change"] }- Default chat: put the declaration in
agents/main/agent.json. That file is read only whenagents/main/AGENT.mdexists and is not empty. - A named agent: add both names to the
toolslist inagents/<name>/agent.json. - A new blank agent: tick Let the agent propose changes to itself when creating it. Amodal writes both
agents/mainfiles.
Commit and deploy the change. The deploy must record its source version; otherwise the tool reports that the agent must be redeployed first.
The Proposals page is always in the Studio sidebar. Studio shows the builder chat only when the agent's active production deployment declares propose_source_change for its main agent or for one of its named agents, in agent.json or, for a named agent, in agent.ts, or when the agent already has a proposal from chat.
What an agent can change
A proposal replaces whole files. It can change or add:
- Markdown under
agents/,skills/, andknowledge/, including the agent's prompt,agents/<name>/AGENT.md(agents/main/AGENT.mdfor default chat) .ts,.mts,.js, and.mjsfiles undertools/<name>/
The runtime reads skills/, knowledge/, and tools/ from amodal/<dir>/ when that directory holds files, and from the top level otherwise. A proposal must use the location this agent loads; one for the other location is refused with the path to use instead. Every other path is refused, including amodal.json, agent.json, agent.ts, tool.json, package.json, connections, and environment files. An agent therefore cannot add a new tool, because a tool needs a tool.json, and cannot widen the connections or secrets it reaches.
Wherever propose_source_change is registered, the agent also gets read_amodal_docs, which reads these docs from docs.amodalai.com: the page index from llms.txt, or one page by its path, such as /guide/connections. The agent looks up the source format there instead of guessing it. Asked for something it cannot propose, such as a Slack connection, the agent tells the user how a person sets it up, from the docs, and does not propose a placeholder skill. It can still propose instructions that use the connection once it exists.
A skill added by a proposal reaches a named agent that lists its skills in agent.json only after someone adds it to that list.
| Limit | Value |
|---|---|
| Files per proposal | 10 |
| Characters per file | 200,000 |
| Characters in the reason | 2,000 |
| Proposals waiting for review | 10 per agent |
| Proposals listed on the page | 50 per page, under Waiting and Decided |
Amodal reads each file's current text itself, at the version the deployment runs, so the diff a reviewer sees is the platform's own. Files left unchanged are dropped, and a proposal that changes nothing is refused.
Builder chat
The builder chat is the chat button at the bottom right of every Studio page of an agent that shows it, as described in Turn it on. Use it to build an agent from Studio alone, starting from a blank agent created with Let the agent propose changes to itself: describe a connection, a policy, a hook, an eval, a store, or a skill, and it proposes the files.
- Who can use it: anyone with permission to edit the agent's source. The button is hidden from everyone else, and from every agent that neither declares
propose_source_changenor has a proposal from chat. - What it reads: every source file at the current source version. Files that do not fit its budget of 160,000 characters are listed by path only.
- What it can propose: creating, replacing, or deleting any source file except
.envfiles, keys, and anything undernode_modules,dist,build,coverage,.git, or.next. It cannot change a file too large to read, or delete a file it could not read. The diff of a deleted file shows every line removed, and its path is marked as deleted. - Secrets: it never writes a secret value. A connection references a credential as
env:NAME, and the builder tells you to addNAMEon the Secrets page. Aspec.jsonthat holds a literal credential is refused. - Format: it writes against the pages of these docs that describe the source layout, connections, hooks, evals, stores, knowledge, skills, and tools, and Amodal checks each connection, store, and eval file and every JSON file, and that a new file sits where this agent loads its directory from, before storing the proposal. When a file does not pass, the builder gets one chance to fix it; otherwise it replies that nothing was proposed and names the problem.
- Model: the model set for issue triage and draft fixes on the Issues page, which is the agent's own model by default. Its calls are billed to the organization.
One chat keeps one waiting proposal. Each reply that writes files replaces it with a new proposal that holds every file so far, and the previous one moves to Decided as discarded. To take a file back out, ask the builder to drop it. A file that changes in the repository after the builder proposed it is left out of the next proposal, and the builder sees the repository's version of it. A reply that finishes after its waiting proposal was approved or discarded proposes nothing and says so; ask again to build on the current source. Resetting the chat starts a new proposal and leaves the previous one waiting. The conversation is not saved.
The builder chat runs on the hosted platform only, not under amodal dev. Its proposals are approved like an agent's, as described below.
Review a proposal
The agent replies with a link to Deploy → Proposals in Studio. Each waiting proposal shows the agent's reason, a diff for each file, the model, who asked for it, and View chat, which opens the conversation that asked for it. A proposal from the builder chat shows "From the builder chat" instead of View chat. The requester is the email of the user whose chat produced the proposal: the builder chat's user, or the owner of the agent chat. It shows the user id for someone outside the organization, and nothing when the chat ran on a token minted with an API key. A waiting proposal with a file that changed since it was proposed names that file and offers only Discard, because approving it would fail; ask for the change again. The page lists waiting proposals under Waiting and approved or discarded ones under Decided, with the count of each on its tab; an approved one shows its commit and deploy. The sidebar shows the number waiting next to Proposals.
- Approve and deploy needs permission to edit source and manage deploys: an organization admin or developer, or the agent's owner or editor.
- Discard needs permission to review feedback, which the same roles hold.
Approvals and discards appear in Activity.
What approving does
Approving asks for confirmation. On a GitHub or GitLab source, the dialog also offers a branch and a commit message:
- Production branch, the default, commits the change and deploys it, as described below.
- New creates a branch from the production branch and commits the change to it. Existing commits the change to another branch you pick. Neither deploys. The success message links to the page that opens a pull request on GitHub or a merge request on GitLab. The proposal moves to Decided with its commit marked "not deployed".
An Amodal-hosted source has no branches, so approving always commits the next source version and deploys it.
Approving onto the production branch:
- Checks that every file still holds the text the agent read. If one changed, approving fails and the agent needs to propose the change again. Approving onto an existing branch checks the files on that branch instead.
- Commits the change.
- On a GitHub or GitLab source, the commit goes onto the production branch: the branch set in Deploys, or the repository's default branch when none is set.
- On an Amodal-hosted source, the commit is the next source version.
- Deploys that commit to production. When Deploys builds on push, the push and the approval share one build of the commit, whichever starts it first, and the proposal links to that build. It goes live when Deploys promotes automatically; otherwise make it live from its deploy page.
An issue fix also commits the issue's regression evals in the same commit, and links the deploy to the issue as its fix, which Activity records as a link fix entry on the issue.
If the commit succeeds but the deploy does not start, the proposal stays approved and the error names the commit. Deploy it from Deploys.