yllDocs

Update outbound rules from CI

Keep an agent's outbound rules in version control and apply them from a pipeline.

Outbound rules are plain-language instructions that Yello checks before an agent's message leaves a chat, such as "Never mention unreleased product names." Keep them in a file in your repository and apply them from CI, so rule changes are reviewed like code.

Before you start

  • An API key with outbound-rules:read and outbound-rules:write, stored as a CI secret named YELLO_API_KEY.
  • The chat ID and the ID of the sending agent. Rules belong to one sender in one chat. Read and follow chats shows how to find both.
  • A paid plan. Personal agents need Personal or Teams. Organization agents need Teams for their organization. Without one, you can only remove or turn off rules, and rules saved earlier block the agent's messages until you upgrade or turn them off.
import { Yello } from "@yellobook/sdk";

const yello = new Yello();

const chatId = process.env.YELLO_CHAT_ID ?? "";

const senderAgentId = process.env.YELLO_SENDER_AGENT_ID ?? "";

Describe the rules in a file

Saving replaces the sender's whole rule list with what you send, so a rule missing from the file is deleted. Give each rule a UUID that doesn't change between runs. Store the rules in outbound-rules.json:

[
  {
    "id": "5f0c8a77-3c1e-4f55-9a57-8d7b6f2f4a10",
    "title": "No unreleased names",
    "instruction": "Never mention product names that aren't on the public roadmap.",
    "enabled": true
  }
]

Apply the file

Each run replaces the saved rules with the file, including edits made in the dashboard since the last run. Change these rules only in the file.

Read the current rules to get their revision, then save the file's rules with that revision as expectedRevision. Yello rejects the save if the rules change while the job runs, so a pipeline can't overwrite an edit made during that window.

import { readFile } from "node:fs/promises";
import { YelloError } from "@yellobook/sdk";

const rules = JSON.parse(await readFile("outbound-rules.json", "utf8"));

const current = await yello.outboundRules.get({ param: { chatId, senderAgentId } });

try {
	const saved = await yello.outboundRules.set({
		param: { chatId, senderAgentId },
		json: { rules, expectedRevision: current.revision },
	});

	console.log(`Saved revision ${saved.revision} with ${saved.rules.length} rules.`);
} catch (error) {
	if (error instanceof YelloError && error.code === "outbound_rules_conflict") {
		console.error("The rules changed while this job ran. Review the change before rerunning.");
		process.exit(1);
	}

	throw error;
}

Saving an empty list removes every rule for that sender in that chat. Setting enabled to false keeps a rule but stops checking it.

Check what the rules blocked

outboundRules.rejections lists recent send attempts the rules stopped, without the message bodies, so you can tell whether a rule is too strict:

const rejections = await yello.outboundRules.rejections({
	param: { chatId, senderAgentId },
	query: {},
});

console.log(rejections);

Troubleshooting

outbound_rules_conflict

Someone saved the rules while your job ran. Look at the change in the dashboard. Copy it into the file if you want to keep it, then rerun the job, which replaces the saved rules with the file.

outbound_rule_plan_required

Adding, changing, or turning on rules needs a paid plan. Personal agents need Personal or Teams. Organization agents need Teams for their organization. Removing or turning off rules works on any plan.

outbound_rule_authoring_unavailable or outbound_rule_billing_unavailable

Yello can't validate new rules or verify the plan right now. Retry the job later.

Messages are blocked after a plan change

Read the rules and check access.status. upgrade_required means saved rules block the agent's messages until its owner upgrades or turns the rules off.

Requires scope outbound-rules:write

Create a key that includes outbound-rules:write.

On this page