forked from molecule-ai/molecule-core
75 lines
2.9 KiB
Python
75 lines
2.9 KiB
Python
"""AGENTS.md auto-generation for Molecule AI workspaces.
|
|
|
|
Implements the AAIF / Linux Foundation AGENTS.md standard so that peer agents
|
|
and orchestration tools can discover this workspace's identity, role, A2A
|
|
endpoint, and available tools without reading the full system prompt.
|
|
|
|
Usage::
|
|
|
|
from agents_md import generate_agents_md
|
|
|
|
generate_agents_md(config_dir="/configs", output_path="/workspace/AGENTS.md")
|
|
|
|
The function is called automatically at container startup (see main.py).
|
|
"""
|
|
|
|
import logging
|
|
import os
|
|
from pathlib import Path
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def generate_agents_md(config_dir: str, output_path: str) -> None:
|
|
"""Generate (or regenerate) AGENTS.md from the workspace config.yaml.
|
|
|
|
Always overwrites ``output_path`` — no stale-file guard. Re-calling
|
|
after editing config.yaml produces a fresh file reflecting the changes.
|
|
|
|
Args:
|
|
config_dir: Directory containing config.yaml (same convention as
|
|
``load_config`` in config.py).
|
|
output_path: Absolute path where AGENTS.md will be written.
|
|
The parent directory is expected to exist.
|
|
"""
|
|
from config import load_config
|
|
|
|
cfg = load_config(config_dir)
|
|
|
|
# ── A2A Endpoint ─────────────────────────────────────────────────────────
|
|
# AGENT_URL env var takes priority (production deployments behind a proxy).
|
|
# Otherwise derive from the configured a2a.port (default 8000).
|
|
endpoint = os.environ.get("AGENT_URL") or f"http://localhost:{cfg.a2a.port}/a2a"
|
|
|
|
# ── Role ─────────────────────────────────────────────────────────────────
|
|
# Fall back to description when the role field is absent so legacy
|
|
# config.yaml files (without a role key) still produce meaningful output.
|
|
role = cfg.role if cfg.role else cfg.description
|
|
|
|
# ── MCP Tools ────────────────────────────────────────────────────────────
|
|
# tools (skill names) + plugins (installed plugin names) form the combined
|
|
# capability surface visible to peer agents.
|
|
all_tools = list(cfg.tools) + list(cfg.plugins)
|
|
if all_tools:
|
|
tools_section = "\n".join(f"- {t}" for t in all_tools)
|
|
else:
|
|
tools_section = "None"
|
|
|
|
content = (
|
|
f"# {cfg.name}\n"
|
|
f"\n"
|
|
f"**Role:** {role}\n"
|
|
f"\n"
|
|
f"## Description\n"
|
|
f"{cfg.description}\n"
|
|
f"\n"
|
|
f"## A2A Endpoint\n"
|
|
f"{endpoint}\n"
|
|
f"\n"
|
|
f"## MCP Tools\n"
|
|
f"{tools_section}\n"
|
|
)
|
|
|
|
Path(output_path).write_text(content, encoding="utf-8")
|
|
logger.info("Generated AGENTS.md at %s for workspace %r", output_path, cfg.name)
|