Building an AI Agent That Manages Custom Domains on Deployxa
Managing custom domains is tedious: you need to add the domain to the platform, configure DNS records, wait for DNS propagation, provision an SSL certificate, verify the routing, and troubleshoot issues. For teams with many apps and many domains, this is a significant operational burden. What you need is an AI agent that manages custom domains automatically: adds domains, configures DNS, provisions SSL, and verifies routing. With the Deployxa MCP server, this is straightforward to build. Here is how.
The direct answer is that a custom domain management agent is a script that uses the Deployxa MCP server to add custom domains (via deployxa_add_domain), check SSL status (via deployxa_get_ssl_status), verify routing (via deployxa_doctor), and troubleshoot issues. The agent uses an LLM to interpret natural language commands (e.g., "add myapp.com to my-app") and to execute them via the MCP server. For more on custom domains, see our article on how we handle SSL at scale.
Why Manual Domain Management Is Tedious
Three problems make manual domain management tedious. First, it is multi-step. Adding a custom domain involves multiple steps (add domain, configure DNS, wait for propagation, provision SSL, verify routing), each of which takes time. Second, it is error-prone. Misconfiguring DNS records, typos in domain names, or incorrect SSL configuration can cause issues that are hard to debug. Third, it does not scale. For teams with many apps and many domains, the operational burden grows linearly, which means it becomes a significant time sink. An AI agent solves all three problems: it automates the multi-step process, it eliminates human error, and it scales to any number of domains. For more on agentic patterns, see our article on building a custom AI deployment assistant.
What the Domain Management Agent Does
The custom domain management agent performs the following tasks:
- Add a custom domain. The agent calls deployxa_add_domain to add a custom domain to an app.
- Provide DNS instructions. The agent provides the DNS records that need to be configured (e.g., CNAME to cname.deployxa.app), and waits for the user to configure them.
- Check DNS propagation. The agent periodically checks whether the DNS has propagated (by resolving the domain and checking if it points to Deployxa).
- Check SSL status. The agent calls deployxa_get_ssl_status to check whether the SSL certificate has been provisioned.
- Verify routing. The agent calls deployxa_doctor to verify that the domain is routing correctly and that the app is healthy.
- Troubleshoot issues. If any step fails (e.g., DNS not propagated, SSL not provisioned, routing not working), the agent uses an LLM to diagnose the issue and recommend a fix.
Step-by-Step: Building the Domain Management Agent
Here is how to build the custom domain management agent in Python, using the Deployxa MCP server and an LLM.
Step 1: Install dependencies
pip install openai requests dnspython
npm install -g @deployxa/mcp-server
deployxa-mcp loginStep 2: Create the agent script
# domain_agent.py
import openai
import requests
import dns.resolver
import time
import json
from datetime import datetime
# Configuration
DEPLOYXA_MCP_URL = "http://localhost:3000/mcp"
SLACK_WEBHOOK_URL = "https://hooks.slack.com/services/..."
DEPLOYXA_CNAME_TARGET = "cname.deployxa.app"
def call_deployxa(tool, params):
response = requests.post(DEPLOYXA_MCP_URL, json={"tool": tool, "params": params})
return response.json()
def send_slack_notification(message, is_alert=False):
emoji = "š" if not is_alert else "šØ"
requests.post(SLACK_WEBHOOK_URL, json={"text": f"{emoji} {message}"})
def check_dns_propagation(domain):
"""Check if the domain's DNS points to Deployxa."""
try:
answers = dns.resolver.resolve(domain, 'CNAME')
for answer in answers:
if DEPLOYXA_CNAME_TARGET in str(answer):
return True
return False
except dns.resolver.NXDOMAIN:
return False
except dns.resolver.NoAnswer:
# Try A record
try:
answers = dns.resolver.resolve(domain, 'A')
# Check if any A record points to Deployxa's IP
# (In a real implementation, you would check against known Deployxa IPs)
return len(answers) > 0
except:
return False
except Exception:
return False
def add_custom_domain(app_id, domain):
"""Add a custom domain to an app."""
print(f"Adding domain {domain} to app {app_id}...")
result = call_deployxa("deployxa_add_domain", {
"app_id": app_id,
"domain": domain,
})
if result.get("status") == "success":
print(f" Domain added. Configure DNS:")
print(f" CNAME {domain} -> {DEPLOYXA_CNAME_TARGET}")
send_slack_notification(
f"Domain {domain} added to app {app_id}.\n"
f"Please configure DNS: CNAME {domain} -> {DEPLOYXA_CNAME_TARGET}"
)
return True
else:
print(f" Failed: {result.get('error')}")
send_slack_notification(f"Failed to add domain {domain}: {result.get('error')}", is_alert=True)
return False
def wait_for_dns(domain, timeout_minutes=60):
"""Wait for DNS to propagate."""
print(f"Waiting for DNS propagation for {domain}...")
start = time.time()
while time.time() - start < timeout_minutes * 60:
if check_dns_propagation(domain):
print(f" DNS propagated")
return True
print(f" DNS not yet propagated, waiting 60 seconds...")
time.sleep(60)
print(f" DNS did not propagate within {timeout_minutes} minutes")
send_slack_notification(f"DNS for {domain} did not propagate within {timeout_minutes} minutes", is_alert=True)
return False
def check_ssl_status(app_id, domain):
"""Check if SSL is provisioned."""
result = call_deployxa("deployxa_get_ssl_status", {
"app_id": app_id,
"domain": domain,
})
ssl_status = result.get("ssl_status", "unknown")
return ssl_status == "active"
def wait_for_ssl(app_id, domain, timeout_minutes=10):
"""Wait for SSL to be provisioned."""
print(f"Waiting for SSL provisioning for {domain}...")
start = time.time()
while time.time() - start < timeout_minutes * 60:
if check_ssl_status(app_id, domain):
print(f" SSL provisioned")
return True
print(f" SSL not yet provisioned, waiting 60 seconds...")
time.sleep(60)
print(f" SSL was not provisioned within {timeout_minutes} minutes")
send_slack_notification(f"SSL for {domain} was not provisioned within {timeout_minutes} minutes", is_alert=True)
return False
def verify_routing(app_id, domain):
"""Verify that the domain is routing correctly."""
result = call_deployxa("deployxa_doctor", {"app_id": app_id})
# Check if the DNS check passed
for check in result.get("checks", []):
if check.get("name") == "DNS resolution" and domain in check.get("detail", ""):
return check.get("status") == "pass"
return result.get("grade") in ["A", "B"]
def setup_custom_domain(app_id, domain):
"""Set up a custom domain end-to-end."""
print(f"\n{'='*60}")
print(f"Setting up custom domain: {domain}")
print(f"{'='*60}")
# Step 1: Add the domain
if not add_custom_domain(app_id, domain):
return False
# Step 2: Wait for DNS propagation
if not wait_for_dns(domain):
return False
# Step 3: Wait for SSL provisioning
if not wait_for_ssl(app_id, domain):
return False
# Step 4: Verify routing
if verify_routing(app_id, domain):
print(f"\nā
Custom domain {domain} is live!")
send_slack_notification(
f"ā
Custom domain {domain} is live!\n"
f" SSL: Active\n"
f" Routing: Verified\n"
f" URL: https://{domain}"
)
return True
else:
print(f"\nā Routing verification failed for {domain}")
send_slack_notification(f"Routing verification failed for {domain}", is_alert=True)
return False
def troubleshoot_domain(app_id, domain):
"""Troubleshoot domain issues using an LLM."""
client = openai.OpenAI()
# Gather diagnostic information
ssl_result = call_deployxa("deployxa_get_ssl_status", {"app_id": app_id, "domain": domain})
doctor_result = call_deployxa("deployxa_doctor", {"app_id": app_id})
dns_propagated = check_dns_propagation(domain)
response = client.chat.completions.create(
model="gpt-4o",
messages=[
{
"role": "system",
"content": "You are a domain troubleshooting agent. Diagnose the domain issue and recommend a fix."
},
{
"role": "user",
"content": f"""Domain: {domain}
DNS propagated: {dns_propagated}
SSL status: {ssl_result.get('ssl_status', 'unknown')}
Doctor grade: {doctor_result.get('grade', 'unknown')}
Doctor checks: {json.dumps(doctor_result.get('checks', []), indent=2)}
Diagnose the issue and recommend a fix.
"""
}
]
)
diagnosis = response.choices[0].message.content
print(f"\nDiagnosis: {diagnosis}")
send_slack_notification(f"Domain {domain} troubleshooting:\n{diagnosis}")
if __name__ == "__main__":
# Example: set up a custom domain
APP_ID = "123"
DOMAIN = "myapp.com"
success = setup_custom_domain(APP_ID, DOMAIN)
if not success:
print("\nSetup failed, troubleshooting...")
troubleshoot_domain(APP_ID, DOMAIN)Step 3: Run the agent
python domain_agent.pyThe agent adds the custom domain, waits for DNS propagation, waits for SSL provisioning, verifies routing, and reports the result via Slack. If any step fails, it troubleshoots the issue using an LLM.
Step 4: Deploy the agent
The agent can be run on-demand (when you need to add a domain) or deployed as a Deployxa app for continuous domain management.
Common Pitfalls and Troubleshooting
The first pitfall is DNS propagation delays. DNS propagation can take anywhere from a few minutes to 48 hours, which means the agent needs to be patient. The fix is to set a long timeout (e.g., 60 minutes) and to check periodically. The second pitfall is DNS misconfiguration. The user might configure the DNS records incorrectly (e.g., wrong CNAME target, wrong record type), which prevents propagation. The fix is to provide clear DNS instructions and to verify the DNS configuration. The third pitfall is SSL provisioning failures. SSL provisioning can fail for various reasons (e.g., Let's Encrypt rate limits, domain validation failures), which means the agent needs to handle failures gracefully. The fix is to retry SSL provisioning and to troubleshoot if retries fail. The fourth pitfall is apex domain issues. Apex domains (e.g., myapp.com) cannot use CNAME records (in standard DNS), which means they need an A record or an ALIAS record. The fix is to provide different instructions for apex domains (A record) and subdomains (CNAME record). The fifth pitfall is wildcard domains. Wildcard domains (e.g., *.myapp.com) require a different SSL certificate (a wildcard certificate), which might need additional configuration. The fix is to handle wildcard domains specially in the agent.
Conclusion: Let the Agent Manage Your Domains
Manual domain management is tedious, error-prone, and does not scale. An AI agent that manages custom domains automatically is the sustainable solution. With the Deployxa MCP server and an LLM, you can build a domain management agent that adds domains, configures DNS, provisions SSL, and verifies routing, all automatically. Stop managing domains manually and start automating.
Ready to build your domain management agent? Install the Deployxa MCP server with npm i -g @deployxa/mcp-server, run deployxa-mcp login, and start building. For more on agentic workflows, see our articles on the agentic log analysis pipeline and building an AI agent that optimizes your database. Learn about the agentic database backup pipeline and building an AI agent that manages your secrets in our companion articles. Explore our free developer tools to speed up your workflow.