Skip to content
Go To Dashboard

Domains & DNS

Domains & DNS let a deployed agent check domain availability, register and renew names, inspect owned domains, manage DNS records, and start a transfer out. Agent steps call the typed ctx.sapiom.domains capability; Sapiom supplies the authenticated cloud connection when the deployed agent runs.

What the agent needsRecommended operation
Availability plus current purchase and renewal quotesdomains.check({ domainNames })
Register one approved domain for one yeardomains.register({ domainName })
Inspect or enumerate owned domainsdomains.get(...) or domains.list()
Extend an owned domain by one yeardomains.renew({ domainName })
Create, inspect, change, or remove DNSdomains.dns.*
Move a domain to another registrardomains.transferOut({ domainName })

Availability can change between check and registration. Treat the returned quote as decision input, not a reservation.

Registration is a real purchase. Require the exact name and a price ceiling from an approval boundary before the step calls register:

const [candidate] = await ctx.sapiom.domains.check({
domainNames: [input.approvedDomain],
});
if (!candidate || candidate.domainName !== input.approvedDomain) {
throw new Error("Availability response did not match the approved domain");
}
if (!candidate.available) {
return { registered: false, reason: "unavailable" };
}
const quotedPrice = Number(candidate.purchasePrice);
if (
!Number.isFinite(input.approvedMaxPurchasePrice) ||
!Number.isFinite(quotedPrice) ||
quotedPrice > input.approvedMaxPurchasePrice
) {
return {
registered: false,
reason: "price-not-approved",
quotedPrice: candidate.purchasePrice ?? null,
};
}
const domain = await ctx.sapiom.domains.register({
domainName: candidate.domainName,
});
return {
registered: true,
domainName: domain.domainName,
expiresAt: domain.expiresAt ?? null,
};

Check accepts 1–50 names and returns decimal purchase and renewal prices as strings when available. Registration and renewal charge on success. Recheck any policy-relevant value at the point of action and handle a registration failure even after a positive availability result.

Use host: "" for the root domain and a label such as "www" or "api" for a subdomain:

const record = await ctx.sapiom.domains.dns.create({
domainName: input.domainName,
type: "A",
host: "",
value: input.ipAddress,
ttl: 300,
});
return {
recordId: record.recordId,
fqdn: record.fqdn ?? record.domainName,
value: record.value,
};

Supported record types are A, AAAA, ANAME, CNAME, MX, TXT, SRV, and NS. TTL has a minimum of 300 seconds and defaults to 300. MX records require priority.

Call domains.dns.list({ domainName }) to obtain record IDs before updating or deleting. An update accepts only the fields that should change, but the agent should read current state first when it must avoid overwriting a concurrent change.

Use domains.get before renewal to inspect current expiry and renewal price. Transfer-out is disruptive: it can unlock the domain and returns an authorization code for the receiving registrar. Keep that code out of logs, shared state, and ordinary agent output, and expose it only through the approved transfer workflow.

Local Run replaces domain and DNS calls with deterministic results. The built-in availability stub marks every requested name available, so never use its default as evidence that a real domain can be purchased.

Override the entire decision path for each test case:

{
"version": 1,
"steps": {
"register-domain": {
"domains.check": [
{
"domainName": "approved-example.dev",
"available": true,
"purchasePrice": "12.99",
"renewalPrice": "12.99",
"premium": false
}
],
"domains.register": {
"domainName": "approved-example.dev",
"status": "active",
"registeredAt": "2099-01-01T00:00:00.000Z",
"expiresAt": "2100-01-01T00:00:00.000Z",
"purchasePrice": "12.99"
}
}
}
}

Use separate fixtures for unavailable, premium, over-budget, DNS, renewal, and transfer branches. After each run, assert the terminal output and require both unusedStubs and stubWarnings to be empty. Local Run never registers, renews, modifies DNS, or starts a transfer.

Track expiry outside the final renewal window, retain the returned domain and record IDs, and verify DNS after changes through the system that will consume it. Domain registration, renewal, and DNS propagation have different lifecycles.

Use the live quotes returned by check and get, plus the signed-in capability catalog for current availability and limits. Do not embed a domain price in agent source.