שישה צעדים מעשיים כדי לשרת קוראים אנושיים וסוכני AI מאותו אתר, עם צ'ק-ליסט להעתקה
בארבעת הימים האחרונים, אני ו-Claude Code הפכנו את smarts.md מאתר תיעוד לחוזים חכמים שנבנה לבני אדם לאתר שנבנה לסוכני AI.
זה נשמע אותו דבר. לא באמת. אתר לבני אדם ממוטב קריאוּת, חיפוש וזמני טעינה. אתר לסוכני AI צריך לענות על שאלות אחרות:
robots.txt ברירת-המחדל נועל אותם בחוץ?הנה שישה דברים שהפעלתי את Claude לבנות. כל אחד שימושי בפני עצמו וניתן לקחת אותו לאתר שלך בנפרד.
robots.txtרוב האתרים יורשים robots.txt מתבנית ישנה שאוסרת באופן משתמע כל User-Agent לא מוכר. אבל אחרי 2025, הרבה זחלני AI הם User-Agents חדשים — GPTBot, ClaudeBot, PerplexityBot, Applebot-Extended, Google-Extended, CCBot, meta-externalagent ועוד. אם אתה רוצה שייכנסו, חייבים להתיר אותם במפורש.
ה-robots.txt של smarts נפתח בהערת מדיניות ואז מפרט User-agent + Allow: / ל-12 זחלנים המכסים את OpenAI, Anthropic, Perplexity, Google Gemini, Apple, Common Crawl, Meta ו-Cohere. העמדה ישירה: האתר הזה קיים כדי ש-AI יקרא אותו.
llms.txt — תפריט ל-LLMsllms.txt הוא מוסכמה שהציע llmstxt.org: שמים קובץ Markdown תמציתי בשורש האתר שמסביר ל-LLM מה האתר הזה, איך משתמשים בו ואיפה נקודות הכניסה העיקריות. זה ה-elevator pitch של האתר שלך.
ה-llms.txt של smarts הוא כ-60 שורות:
/{chain}/{address} לעומת slug קצר)התובנה: LLMs משלמים בטוקנים כדי לקרוא את התיעוד שלך, לכן לא יעשו זחילה של האתר כולו. תן להם אינדקס מזוקק והפגיעה זינוק.
.well-known/mcp.json — הימור מוקדםפרוטוקול MCP עדיין לא תיקנן מוסכמת discovery מעין /.well-known/openid-configuration. היום שום client ציבורי לא עושה זחילה לנתיב well-known קבוע.
אבל פרסום המניפסט עולה 30 שורות:
def well_known_mcp
response.set_header("Cache-Control", "public, max-age=3600")
response.set_header("Access-Control-Allow-Origin", "*")
render json: {
name: "smarts",
version: "0.1.0",
description: "...",
protocol_version: "2024-11-05",
transports: [{ type: "sse", endpoint: "https://smarts.md/mcp/sse" }],
capabilities: { tools: true, resources: false, prompts: false },
tools: MCP_TOOLS.map { |t| { name: t[:name], description: t[:blurb] } }
}
end
ברגע שתופיע מוסכמת discovery, אני לא מחליף אפילו שורה אחת. במקביל זה תיעוד-עצמי למפתחים — כל מי שסקרן לגבי ה-MCP שלי פשוט מריץ curl smarts.md/.well-known/mcp.json.
הטריק: מערך tools נגזר מהקבוע MCP_TOOLS, מקור-אמת יחיד. מבחן מבני קיים כופה שכל app/tools/*_tool.rb יופיע באותו קבוע, כך שהמניפסט יורש בחינם את ההבטחה ש"כלי חדש לא יישכח".
.md: זיקוק ידידותי ל-WebFetch לכל עמודהאהוב עליי. כלי ה-WebFetch של Claude Code צריך לנקות ולחלץ תוכן מ-HTML שרירותי — יקר בטוקנים ולא אמין. מה אם מגישים .md ישירות?
respond_to של Rails תומך בכך באופן מובנה:
# config/routes.rb
get ":slug(.:format)", to: "contracts#show",
constraints: { slug: ContractSlugs::ROUTE_PATTERN, format: /html|md/ }
https://smarts.md/usdc-eth מחזיר HTML; https://smarts.md/usdc-eth.md מחזיר 40 שורות Markdown — כתובת, רשת, סיווג, endpoint של MCP, איך לשאול דרך סוכן AI, קישורי מקור.
# USD Coin on Ethereum
- **Address:** `0xa0b8...`
- **Chain:** Ethereum
- **Classification:** ERC-20 Token
## Query via AI agent
- **MCP endpoint:** `https://smarts.md/mcp/sse`
- **Reference:** `usdc-eth`
- **Sample prompt:** "Tell me the current state of usdc-eth"
fetch אחד, כל התוכן המובנה שסוכן AI רוצה נמצא בפנים, בלי צורך בפרסר DOM. Claude סגר את זה מהר — controller אחד, שני תבניות .md.erb, (.:format) ב-routes, סיימנו.
זו תגלית בכיוון הפוך: חלק מהמבקרים שלי כבר משתמשים ב-Claude Code / Cursor / Windsurf. הם נוחתים על עמוד חוזה והצעד הבא הוא בדרך כלל "שה-AI שלי יסתכל על זה".
אז בכל עמוד חוזה מופיע כרטיס עם:
usdc-eth) או chain/address, עם כפתור העתקהmcp.smarts.md (הקמה בשורה אחת)לחיצה אחת של חיכוך בין "אני מסתכל על החוזה הזה" ל"אני שואל את ה-AI שלי". הכרטיס משתמש ב-card של DaisyUI וב-controller Stimulus גנרי copy — 50 שורות erb. מבחן רגרסיה נועל את מאפייני data-copy-text-value כדי שרפקטור עתידי לא ידביק בשקט מחרוזת שגויה ללוח של המשתמשים.
OpenGraph, Twitter Card, JSON-LD — שכבת החיפוש והכרטיסים החברתיים המסורתית. שווה לטפל, כי גם זחלני AI קוראים פה.
הבחירה המעניינת: איך JSON-LD צריך לתאר חוזה חכם. Claude בחר WebPage העוטף SoftwareApplication:
{
"@type": "WebPage",
"about": {
"@type": "SoftwareApplication",
"name": "USD Coin",
"applicationCategory": "SmartContract",
"operatingSystem": "Ethereum",
"identifier": "0xa0b8..."
}
}
operatingSystem מקבל את שם הרשת, identifier את הכתובת, additionalType את הסיווג (למשל "Uniswap V3 Pool"). ב-schema.org אין טיפוס ייעודי SmartContract, אבל SoftwareApplication פלוס השדות האלה מספיקים כדי ש-LLM יבין "זה חוזה על Ethereum עם כתובת ספציפית".
תמונת ה-OG היא summary_large_image בגודל 1200×630; Twitter Card, breadcrumbs, softwareVersion ו-license משלימים את התמונה.
שש הפריטים למעלה יצאו משבע PR-ים בארבעה ימים:
| PR | קבצים | גודל |
|---|---|---|
feat/ai-crawler-discovery |
2 | ~126 loc |
feat/well-known-mcp-manifest |
4 | ~129 loc |
feat/markdown-contract-pages |
6 | ~298 loc |
feat/contract-mcp-card |
3 | ~126 loc |
feat/seo-meta-tags |
8 | ~292 loc |
feat/seo-enrichments |
8 | ~189 loc |
feat/og-card |
— | — |
כל אחד PR עצמאי עם מבחנים משלו ועם הודעת commit משלו. קצב החיתוך הדק הזה הוא הדבר הכי בעל ערך בעבודה עם Claude — כל PR קטן מספיק כדי לעבור על ה-diff במבט אחד, אבל כשמערימים אותם יחד, לאתר צמח משטח AI שלם.
אם יש לך אתר תוכן ואתה רוצה להפוך אותו לידידותי ל-AI, עשה זאת בסדר הזה:
robots.txt/llms.txt (תפריט מזוקק).md לעמודי התוכן המרכזיים שלך/.well-known/mcp.jsonעל חמשת הראשונים רוב מהנדסי ה-SEO לא יספרו לך — הם לא בפלייבוק הקלאסי. אבל מארבעת ימי הנתונים שלי, עקומת תנועת ה-AI ועקומת תנועת בני האדם הן שתי סדרות עצמאיות לגמרי. חייבים לשרת את שתיהן.