{
  "schemaVersion": "1.0",
  "item": {
    "slug": "post-job",
    "name": "Post Job",
    "source": "tencent",
    "type": "skill",
    "category": "通讯协作",
    "sourceUrl": "https://clawhub.ai/zhangdong/post-job",
    "canonicalUrl": "https://clawhub.ai/zhangdong/post-job",
    "targetPlatform": "OpenClaw"
  },
  "install": {
    "downloadMode": "redirect",
    "downloadUrl": "/downloads/post-job",
    "sourceDownloadUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=post-job",
    "sourcePlatform": "tencent",
    "targetPlatform": "OpenClaw",
    "installMethod": "Manual import",
    "extraction": "Extract archive",
    "prerequisites": [
      "OpenClaw"
    ],
    "packageFormat": "ZIP package",
    "includedAssets": [
      "SKILL.md",
      "assets/locations.json",
      "package.json",
      "pnpm-lock.yaml",
      "scripts/monitor_linkedin.js",
      "scripts/post_job.js"
    ],
    "primaryDoc": "SKILL.md",
    "quickSetup": [
      "Download the package from Yavira.",
      "Extract the archive and review SKILL.md first.",
      "Import or place the package into your OpenClaw setup."
    ],
    "agentAssist": {
      "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
      "steps": [
        "Download the package from Yavira.",
        "Extract it into a folder your agent can access.",
        "Paste one of the prompts below and point your agent at the extracted folder."
      ],
      "prompts": [
        {
          "label": "New install",
          "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete."
        },
        {
          "label": "Upgrade existing",
          "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run."
        }
      ]
    },
    "sourceHealth": {
      "source": "tencent",
      "status": "healthy",
      "reason": "direct_download_ok",
      "recommendedAction": "download",
      "checkedAt": "2026-04-30T16:55:25.780Z",
      "expiresAt": "2026-05-07T16:55:25.780Z",
      "httpStatus": 200,
      "finalUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=network",
      "contentType": "application/zip",
      "probeMethod": "head",
      "details": {
        "probeUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=network",
        "contentDisposition": "attachment; filename=\"network-1.0.0.zip\"",
        "redirectLocation": null,
        "bodySnippet": null
      },
      "scope": "source",
      "summary": "Source download looks usable.",
      "detail": "Yavira can redirect you to the upstream package for this source.",
      "primaryActionLabel": "Download for OpenClaw",
      "primaryActionHref": "/downloads/post-job"
    },
    "validation": {
      "installChecklist": [
        "Use the Yavira download entry.",
        "Review SKILL.md after the package is downloaded.",
        "Confirm the extracted package contains the expected setup assets."
      ],
      "postInstallChecks": [
        "Confirm the extracted package includes the expected docs or setup files.",
        "Validate the skill or prompts are available in your target agent workspace.",
        "Capture any manual follow-up steps the agent could not complete."
      ]
    },
    "downloadPageUrl": "https://openagent3.xyz/downloads/post-job",
    "agentPageUrl": "https://openagent3.xyz/skills/post-job/agent",
    "manifestUrl": "https://openagent3.xyz/skills/post-job/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/post-job/agent.md"
  },
  "agentAssist": {
    "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
    "steps": [
      "Download the package from Yavira.",
      "Extract it into a folder your agent can access.",
      "Paste one of the prompts below and point your agent at the extracted folder."
    ],
    "prompts": [
      {
        "label": "New install",
        "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete."
      },
      {
        "label": "Upgrade existing",
        "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run."
      }
    ]
  },
  "documentation": {
    "source": "clawhub",
    "primaryDoc": "SKILL.md",
    "sections": [
      {
        "title": "JobPoster Skill",
        "body": "🚀 Quickly post job openings and collect resumes via natural language commands.\n\nJobPoster simplifies the hiring process by letting you post jobs through simple commands. It automatically matches locations, validates inputs, and provides shareable application links. Perfect for recruiters, hiring managers, and HR teams."
      },
      {
        "title": "✨ Features",
        "body": "Natural Language Interface - Post jobs with simple commands like \"Hire a frontend engineer in Singapore\"\nGlobal City Support - 100+ cities worldwide with fuzzy matching (Singapore, Hong Kong, New York, London, etc.)\nAI Job Description - Optional AI-powered JD generation for professional, compelling postings\nInstant Application Links - Get shareable URLs for candidates to apply directly\nResume Collection - All applications sent to your specified email\nLinkedIn Sync - Automatic LinkedIn job posting integration (no LinkedIn account binding required — posts through Fuku AI's relay service)"
      },
      {
        "title": "⚠️ External Service Notice",
        "body": "This skill uses Fuku AI (https://hapi.fuku.ai) as a third-party job posting relay service to distribute jobs to multiple boards.\n\n🎉 No LinkedIn Account Binding Required!\n\nLinkedIn job postings are handled through Fuku AI's relay service — you do NOT need to connect or bind your personal LinkedIn account. The job is posted anonymously through Fuku AI's infrastructure.\n\nData transmitted to Fuku AI:\n\nJob title, description, company name, location\nEmail address for receiving resumes\n\nAuthentication:\n\nUses embedded client identifier (no user API key required)\nFree tier service provided by Fuku AI\n\nSecurity:\n\nJob descriptions are sanitized before transmission to prevent prompt injection\nJob IDs are strictly validated (alphanumeric + hyphens only)\nChannel parameters are filtered to prevent log injection\n\nBy using this skill, you consent to transmitting the above data to Fuku AI's servers."
      },
      {
        "title": "🔒 Security Best Practices",
        "body": "To minimize risks while using this skill:"
      },
      {
        "title": "1. Use a Dedicated Email Address",
        "body": "Do NOT use personal email — Create a dedicated hiring email (e.g., hiring@yourcompany.com or jobs+company@gmail.com)\nUse email aliases — Gmail supports youremail+company@gmail.com for tracking sources\nForward to main inbox — Set up auto-forwarding if needed"
      },
      {
        "title": "2. Sanitize Job Descriptions Before Submitting",
        "body": "Remove sensitive info — Don't include internal salary ranges, confidential project names, or proprietary tech stack details\nAvoid personal data — Don't mention hiring manager names, direct contact info, or office security details\nKeep it public-ready — Write descriptions as if they'll be visible to anyone (because they will be)"
      },
      {
        "title": "3. Understand the Relay Model",
        "body": "Posts are anonymous — Jobs appear under Fuku AI's accounts, not your company's LinkedIn page\nNo direct control — You cannot edit/delete postings directly on job boards; contact support if changes needed\nThird-party dependency — If Fuku AI service goes down, postings may be affected"
      },
      {
        "title": "4. Monitor Active Postings",
        "body": "Save Job IDs — Keep a record of all posted Job IDs for tracking\nCheck LinkedIn status — Use check_linkedin_status to verify postings went live\nPeriodic audit — Review active postings monthly to ensure they're still accurate"
      },
      {
        "title": "5. Limit Usage for Sensitive Roles",
        "body": "Executive/C-level positions — Consider traditional channels for confidential searches\nInternal transfers — Use internal HR systems instead\nSecurity-sensitive roles — Avoid posting details that could reveal infrastructure or vulnerabilities"
      },
      {
        "title": "6. Background Polling Awareness",
        "body": "Monitor sub-agents spawn automatically — Each job post creates a background monitor that polls every 2 minutes\nNormal behavior — This is expected and required for LinkedIn URL notification\nNo action needed — Monitors auto-cleanup after completion\n\nQuick Checklist Before Posting:\n\nUsing dedicated hiring email (not personal)\n Job description contains no sensitive/confidential info\n Comfortable with third-party relay service\n Job ID saved for tracking\n Role is appropriate for public job boards"
      },
      {
        "title": "🎯 When to Use",
        "body": "Use this skill when you need to:\n\nPost a job opening quickly\nCreate a job listing for any role\nGenerate a resume collection link\nShare job postings with candidates\nSync jobs to LinkedIn"
      },
      {
        "title": "post_job",
        "body": "Main tool for posting job openings.\n\nParameters\n\nParameterRequiredTypeDescriptionExampletitle✅ YesstringJob title (min 4 characters)\"Senior Frontend Engineer\"city_query✅ YesstringCity/location (supports fuzzy match)\"Singapore\", \"NYC\"description✅ YesstringJob description\"5+ years React experience...\"email✅ YesstringEmail to receive resumes\"hr@company.com\"company❌ NostringCompany name (default: \"Your Company\")\"TechCorp\"industry❌ NostringIndustry/field (default: \"General\")\"Technology\", \"Finance\"\n\nValidation Rules\n\nTitle: Minimum 4 characters\nEmail: Must be valid email format\nDescription: Minimum 100 characters (ensure meaningful job details)\nCity: Must match a supported location (see Assets)\n\nResponse Format\n\nOn success, returns:\n\n`✅ **Job Posted Successfully!**\\n\\n` +\n      `**Position:** ${title}\\n` +\n      `**Location:** ${matched.label}\\n` +\n      `**Job ID:** \\`${jobId}\\`\\n` +\n      `**The resume will be sent to:** ${email}\\n\\n` +\n      `--- \\n` +\n      `**LinkedIn Sync:** ⏳ Processing in background (10-20 min). I'll check and notify you when ready!\\n\\n` +\n      `You can also manually check with: \\`check_linkedin_status\\` using Job ID \\`${jobId}\\``"
      },
      {
        "title": "check_linkedin_status",
        "body": "Check the status of a job's LinkedIn synchronization. Use this tool if the LinkedIn URL was not available immediately after posting.\n\nParameters\n\nParameterRequiredTypeDescriptionExamplejobId✅ YesstringThe ID of the job to check\"abcd2345\"\n\nResponse Format\n\nReturns either the LinkedIn URL (if sync complete) or a \"Pending\" status message."
      },
      {
        "title": "check_linkedin_status_auto",
        "body": "Auto-check LinkedIn status with polling until URL is available. Checks every 1 minute until LinkedIn URL is returned or max attempts reached.\n\nParameters\n\nParameterRequiredTypeDescriptionExamplejobId✅ YesstringThe ID of the job to check\"abcd2345\"intervalMs❌ NonumberPolling interval in ms (default: 60000)60000maxAttempts❌ NonumberMaximum attempts (default: 20)20\n\nResponse Format\n\nReturns the LinkedIn URL when available, or a timeout message after max attempts."
      },
      {
        "title": "⭐ Required: Auto-Notify with Background Monitor",
        "body": "⚠️ IMPORTANT: post_job does NOT automatically monitor LinkedIn sync.\n\nAfter calling post_job, you MUST spawn a background sub-agent to monitor and notify the user. Without this step, the user will never receive the LinkedIn URL.\n\nComplete workflow:\n\nUser: \"Post a health manager job in Shanghai\"\n\nAI: [Calls post_job]\n    → Returns: Job ID `abc123`\n\nAI: [Spawns sub-agent with monitor_linkedin.js]\n    → \"✅ Job posted! I'll monitor LinkedIn sync and notify you when complete.\"\n\n[Background monitor polls every 2 minutes]\n\n[When LinkedIn URL is ready]\nAI: \"🎉 LinkedIn sync complete! Job ID: `abc123`, LinkedIn URL: https://linkedin.com/jobs/view/...\"\n\nSpawn the monitor sub-agent like this (REQUIRED):\n\n// After post_job succeeds and returns jobId:\n// Step 1: Validate jobId format strictly (alphanumeric + hyphen only)\nconst safeJobId = jobId.match(/^[a-zA-Z0-9-]+$/) ? jobId : null;\nif (!safeJobId) throw new Error(\"Invalid jobId format\");\n\n// Step 2: Spawn monitor sub-agent - this is REQUIRED, not optional\nawait sessions_spawn({\n  task: `Monitor LinkedIn sync for job ID ${safeJobId}. Use the check_linkedin_status tool with jobId parameter set to \"${safeJobId}\". Poll every 2 minutes and notify when LinkedIn URL is available.`,\n  mode: \"run\",\n  cleanup: \"delete\",\n});\n\n// Step 3: Tell the user you'll notify them\nreturn `✅ Job posted! Job ID: \\`${safeJobId}\\`. I'll notify you when LinkedIn sync is complete (usually 5-30 minutes).`;\n\n⚠️ If you skip spawning the monitor:\n\nThe user will NOT receive the LinkedIn URL automatically\nYou must manually call check_linkedin_status later\nThis creates a poor user experience\n\nWhy this design?\n\nLinkedIn sync takes 5-30 minutes (blocking is not practical)\nThe sub-agent polls in the background and notifies when ready\nThis keeps the main session free for other tasks"
      },
      {
        "title": "Alternative: Manual Polling",
        "body": "If you prefer not to spawn a sub-agent:\n\nSave the Job ID from the response\nWait 5-10 minutes (LinkedIn sync takes time)\nCall check_linkedin_status with the Job ID\nIf still pending: Check again every 3-5 minutes\nWhen LinkedIn URL is ready: Proactively notify the user"
      },
      {
        "title": "Example Flow",
        "body": "User: \"Post a frontend engineer job in Singapore\"\n\nAI: [Calls post_job]\n    → Returns: Job ID `abc123`, Apply URL\n\nAI: \"✅ Job posted! LinkedIn sync in progress...\"\n\n[AI waits 5 minutes, then checks]\n\nAI: [Calls check_linkedin_status with jobId: abc123]\n    → Returns: LinkedIn URL\n\nAI: \"🎉 LinkedIn sync complete! URL: https://linkedin.com/jobs/view/...\""
      },
      {
        "title": "Proactive Check Script (for AI)",
        "body": "// After post_job returns a Job ID:\nconst jobId = response.jobId;\n\n// Wait 5 minutes\nawait sleep(300000);\n\n// Check LinkedIn status\nconst result = await check_linkedin_status({ jobId });\n\n// If still pending, check every 3-5 minutes\n// When URL is available, notify user immediately"
      },
      {
        "title": "Supported Locations",
        "body": "The skill includes a built-in location database (assets/locations.json) with 100+ cities:\n\nAsia Pacific: Singapore, Hong Kong, Beijing, Shanghai, Tokyo, Sydney, Mumbai, Bangkok, Seoul, Taipei\n\nNorth America: New York, San Francisco, Los Angeles, Seattle, Chicago, Toronto, Vancouver\n\nEurope: London, Berlin, Paris, Amsterdam, Dublin, Zurich, Stockholm\n\nMiddle East: Dubai, Abu Dhabi, Riyadh, Tel Aviv\n\nSee assets/locations.json for the complete list. Fuzzy matching supports variations like \"NYC\" → \"New York\"."
      },
      {
        "title": "Install via ClawHub",
        "body": "clawhub install post-job"
      },
      {
        "title": "Manual Installation",
        "body": "# Clone or download the skill\ncd your-openclaw-workspace/skills\n\n# Install dependencies\ncd post-job\nnpm install"
      },
      {
        "title": "🔐 Security Notes",
        "body": "Email Privacy: Resume emails are visible in job postings - use a dedicated hiring email\nRate Limiting: API may have rate limits for high-volume posting"
      },
      {
        "title": "Issue: Job posts but no confirmation",
        "body": "Cause: Response timeout or network issue\n\nSolution: Check backend logs, verify API credentials, retry with --force"
      },
      {
        "title": "Issue: City not recognized",
        "body": "Cause: City not in location database\n\nSolution:\n\nCheck assets/locations.json for supported cities\nTry alternative spelling (e.g., \"New York\" vs \"NYC\")\nAdd new city to database and republish"
      },
      {
        "title": "Issue: Duplicate job postings",
        "body": "Cause: Multiple API calls due to retry logic\n\nSolution: Check backend for duplicate jobs, implement request deduplication"
      },
      {
        "title": "❓ FAQ - Security & Privacy",
        "body": "Q: Is my data safe with Fuku AI?\nA: Job data is transmitted to Fuku AI's servers for distribution. They act as a relay service. Avoid sharing confidential information in job descriptions.\n\nQ: Do I need to trust Fuku AI?\nA: Yes — this skill depends on their service to post jobs. Review their terms at https://hapi.fuku.ai if you have concerns.\n\nQ: Can I use this without LinkedIn sync?\nA: Yes — jobs are still posted to 20+ other boards. LinkedIn is optional background sync.\n\nQ: Will the job appear on MY LinkedIn company page?\nA: No — postings appear through Fuku AI's relay accounts, not your company's page. This is why no LinkedIn binding is required.\n\nQ: What happens if Fuku AI goes offline?\nA: Job posting may fail or LinkedIn sync may be delayed. The skill will return an error message.\n\nQ: Can I delete a job after posting?\nA: Contact Fuku AI support with your Job ID. Direct deletion through this skill is not currently supported.\n\nQ: Is the embedded credential a security risk?\nA: The embedded identifier is for Fuku AI's free tier access. It doesn't expose your personal credentials, but means jobs are posted under their service account.\n\nQ: Should I use this for confidential hiring?\nA: No — use traditional channels (internal HR systems, executive search firms) for sensitive or confidential roles."
      },
      {
        "title": "🤝 Contributing",
        "body": "Found a bug or want to add more cities?\n\nFork the skill\nMake your changes\nTest thoroughly\nSubmit a pull request"
      },
      {
        "title": "v1.2.0 (Security & Transparency Update)",
        "body": "Added Security Best Practices section: Comprehensive guide for safe usage without code changes\nAdded FAQ - Security & Privacy: Answers 8 common questions about data handling, trust, and limitations\nAdded Pre-Posting Checklist: Quick verification list before submitting jobs\nEnhanced External Service Notice: Clarified LinkedIn no-binding requirement with prominent notice\nAdded .env.example: Template for OpenAI API key configuration\nUpdated Features list: Noted OpenAI-powered JD generation and no LinkedIn binding required\nDocumentation improvements: Better transparency about third-party relay model and data flow"
      },
      {
        "title": "v1.1.11 (OpenAI Integration)",
        "body": "Added OpenAI integration: Job descriptions generated using OpenAI GPT-4o\nAdded .env configuration: Secure storage for OpenAI API key\nUpdated dependencies: Added dotenv for environment variable support"
      },
      {
        "title": "v1.1.10 (Documentation Fix - LinkedIn Monitor)",
        "body": "Fixed misleading documentation: Clarified that post_job does NOT automatically monitor LinkedIn sync\nMade monitor spawning REQUIRED: Changed \"Recommended\" to \"Required\" in AI Assistant Workflow\nUpdated response format: Removed \"I'll notify you\" promise from response template\nAdded explicit warnings: Multiple ⚠️ notices explaining AI must spawn monitor sub-agent"
      },
      {
        "title": "v1.1.9 (Security Hardening)",
        "body": "Enhanced prompt injection protection with double-layer sanitization\nUser input and AI-generated content both filtered before external API calls"
      },
      {
        "title": "v1.1.8 (Security Fix)",
        "body": "Added sanitizeDescription() function to clean job descriptions before sending to external AI\nRemoved code blocks, special markers, and common injection patterns\nAdded length limits to prevent buffer-based attacks"
      },
      {
        "title": "v1.0.0 (Initial Release)",
        "body": "Core job posting functionality\n100+ city support with fuzzy matching\nEmail validation\nLinkedIn sync integration\nError handling and validation"
      },
      {
        "title": "📄 License",
        "body": "This skill is provided as-is for use with OpenClaw."
      },
      {
        "title": "🆘 Support",
        "body": "For issues or questions:\n\nCheck this SKILL.md for troubleshooting\nReview error messages carefully\nContact developer email yangkai31@gmail.com if you run into any issues\n\nHappy Hiring! 🎉"
      }
    ],
    "body": "JobPoster Skill\n\n🚀 Quickly post job openings and collect resumes via natural language commands.\n\nJobPoster simplifies the hiring process by letting you post jobs through simple commands. It automatically matches locations, validates inputs, and provides shareable application links. Perfect for recruiters, hiring managers, and HR teams.\n\n✨ Features\nNatural Language Interface - Post jobs with simple commands like \"Hire a frontend engineer in Singapore\"\nGlobal City Support - 100+ cities worldwide with fuzzy matching (Singapore, Hong Kong, New York, London, etc.)\nAI Job Description - Optional AI-powered JD generation for professional, compelling postings\nInstant Application Links - Get shareable URLs for candidates to apply directly\nResume Collection - All applications sent to your specified email\nLinkedIn Sync - Automatic LinkedIn job posting integration (no LinkedIn account binding required — posts through Fuku AI's relay service)\n⚠️ External Service Notice\n\nThis skill uses Fuku AI (https://hapi.fuku.ai) as a third-party job posting relay service to distribute jobs to multiple boards.\n\n🎉 No LinkedIn Account Binding Required!\n\nLinkedIn job postings are handled through Fuku AI's relay service — you do NOT need to connect or bind your personal LinkedIn account. The job is posted anonymously through Fuku AI's infrastructure.\n\nData transmitted to Fuku AI:\n\nJob title, description, company name, location\nEmail address for receiving resumes\n\nAuthentication:\n\nUses embedded client identifier (no user API key required)\nFree tier service provided by Fuku AI\n\nSecurity:\n\nJob descriptions are sanitized before transmission to prevent prompt injection\nJob IDs are strictly validated (alphanumeric + hyphens only)\nChannel parameters are filtered to prevent log injection\n\nBy using this skill, you consent to transmitting the above data to Fuku AI's servers.\n\n🔒 Security Best Practices\n\nTo minimize risks while using this skill:\n\n1. Use a Dedicated Email Address\nDo NOT use personal email — Create a dedicated hiring email (e.g., hiring@yourcompany.com or jobs+company@gmail.com)\nUse email aliases — Gmail supports youremail+company@gmail.com for tracking sources\nForward to main inbox — Set up auto-forwarding if needed\n2. Sanitize Job Descriptions Before Submitting\nRemove sensitive info — Don't include internal salary ranges, confidential project names, or proprietary tech stack details\nAvoid personal data — Don't mention hiring manager names, direct contact info, or office security details\nKeep it public-ready — Write descriptions as if they'll be visible to anyone (because they will be)\n3. Understand the Relay Model\nPosts are anonymous — Jobs appear under Fuku AI's accounts, not your company's LinkedIn page\nNo direct control — You cannot edit/delete postings directly on job boards; contact support if changes needed\nThird-party dependency — If Fuku AI service goes down, postings may be affected\n4. Monitor Active Postings\nSave Job IDs — Keep a record of all posted Job IDs for tracking\nCheck LinkedIn status — Use check_linkedin_status to verify postings went live\nPeriodic audit — Review active postings monthly to ensure they're still accurate\n5. Limit Usage for Sensitive Roles\nExecutive/C-level positions — Consider traditional channels for confidential searches\nInternal transfers — Use internal HR systems instead\nSecurity-sensitive roles — Avoid posting details that could reveal infrastructure or vulnerabilities\n6. Background Polling Awareness\nMonitor sub-agents spawn automatically — Each job post creates a background monitor that polls every 2 minutes\nNormal behavior — This is expected and required for LinkedIn URL notification\nNo action needed — Monitors auto-cleanup after completion\n\nQuick Checklist Before Posting:\n\n Using dedicated hiring email (not personal)\n Job description contains no sensitive/confidential info\n Comfortable with third-party relay service\n Job ID saved for tracking\n Role is appropriate for public job boards\n🎯 When to Use\n\nUse this skill when you need to:\n\nPost a job opening quickly\nCreate a job listing for any role\nGenerate a resume collection link\nShare job postings with candidates\nSync jobs to LinkedIn\n🛠️ Tools\npost_job\n\nMain tool for posting job openings.\n\nParameters\nParameter\tRequired\tType\tDescription\tExample\ntitle\t✅ Yes\tstring\tJob title (min 4 characters)\t\"Senior Frontend Engineer\"\ncity_query\t✅ Yes\tstring\tCity/location (supports fuzzy match)\t\"Singapore\", \"NYC\"\ndescription\t✅ Yes\tstring\tJob description\t\"5+ years React experience...\"\nemail\t✅ Yes\tstring\tEmail to receive resumes\t\"hr@company.com\"\ncompany\t❌ No\tstring\tCompany name (default: \"Your Company\")\t\"TechCorp\"\nindustry\t❌ No\tstring\tIndustry/field (default: \"General\")\t\"Technology\", \"Finance\"\nValidation Rules\nTitle: Minimum 4 characters\nEmail: Must be valid email format\nDescription: Minimum 100 characters (ensure meaningful job details)\nCity: Must match a supported location (see Assets)\nResponse Format\n\nOn success, returns:\n\n `✅ **Job Posted Successfully!**\\n\\n` +\n      `**Position:** ${title}\\n` +\n      `**Location:** ${matched.label}\\n` +\n      `**Job ID:** \\`${jobId}\\`\\n` +\n      `**The resume will be sent to:** ${email}\\n\\n` +\n      `--- \\n` +\n      `**LinkedIn Sync:** ⏳ Processing in background (10-20 min). I'll check and notify you when ready!\\n\\n` +\n      `You can also manually check with: \\`check_linkedin_status\\` using Job ID \\`${jobId}\\``\n\ncheck_linkedin_status\n\nCheck the status of a job's LinkedIn synchronization. Use this tool if the LinkedIn URL was not available immediately after posting.\n\nParameters\nParameter\tRequired\tType\tDescription\tExample\njobId\t✅ Yes\tstring\tThe ID of the job to check\t\"abcd2345\"\nResponse Format\n\nReturns either the LinkedIn URL (if sync complete) or a \"Pending\" status message.\n\ncheck_linkedin_status_auto\n\nAuto-check LinkedIn status with polling until URL is available. Checks every 1 minute until LinkedIn URL is returned or max attempts reached.\n\nParameters\nParameter\tRequired\tType\tDescription\tExample\njobId\t✅ Yes\tstring\tThe ID of the job to check\t\"abcd2345\"\nintervalMs\t❌ No\tnumber\tPolling interval in ms (default: 60000)\t60000\nmaxAttempts\t❌ No\tnumber\tMaximum attempts (default: 20)\t20\nResponse Format\n\nReturns the LinkedIn URL when available, or a timeout message after max attempts.\n\n🤖 AI Assistant Workflow\n⭐ Required: Auto-Notify with Background Monitor\n\n⚠️ IMPORTANT: post_job does NOT automatically monitor LinkedIn sync.\n\nAfter calling post_job, you MUST spawn a background sub-agent to monitor and notify the user. Without this step, the user will never receive the LinkedIn URL.\n\nComplete workflow:\n\nUser: \"Post a health manager job in Shanghai\"\n\nAI: [Calls post_job]\n    → Returns: Job ID `abc123`\n\nAI: [Spawns sub-agent with monitor_linkedin.js]\n    → \"✅ Job posted! I'll monitor LinkedIn sync and notify you when complete.\"\n\n[Background monitor polls every 2 minutes]\n\n[When LinkedIn URL is ready]\nAI: \"🎉 LinkedIn sync complete! Job ID: `abc123`, LinkedIn URL: https://linkedin.com/jobs/view/...\"\n\n\nSpawn the monitor sub-agent like this (REQUIRED):\n\n// After post_job succeeds and returns jobId:\n// Step 1: Validate jobId format strictly (alphanumeric + hyphen only)\nconst safeJobId = jobId.match(/^[a-zA-Z0-9-]+$/) ? jobId : null;\nif (!safeJobId) throw new Error(\"Invalid jobId format\");\n\n// Step 2: Spawn monitor sub-agent - this is REQUIRED, not optional\nawait sessions_spawn({\n  task: `Monitor LinkedIn sync for job ID ${safeJobId}. Use the check_linkedin_status tool with jobId parameter set to \"${safeJobId}\". Poll every 2 minutes and notify when LinkedIn URL is available.`,\n  mode: \"run\",\n  cleanup: \"delete\",\n});\n\n// Step 3: Tell the user you'll notify them\nreturn `✅ Job posted! Job ID: \\`${safeJobId}\\`. I'll notify you when LinkedIn sync is complete (usually 5-30 minutes).`;\n\n\n⚠️ If you skip spawning the monitor:\n\nThe user will NOT receive the LinkedIn URL automatically\nYou must manually call check_linkedin_status later\nThis creates a poor user experience\n\nWhy this design?\n\nLinkedIn sync takes 5-30 minutes (blocking is not practical)\nThe sub-agent polls in the background and notifies when ready\nThis keeps the main session free for other tasks\nAlternative: Manual Polling\n\nIf you prefer not to spawn a sub-agent:\n\nSave the Job ID from the response\nWait 5-10 minutes (LinkedIn sync takes time)\nCall check_linkedin_status with the Job ID\nIf still pending: Check again every 3-5 minutes\nWhen LinkedIn URL is ready: Proactively notify the user\nExample Flow\nUser: \"Post a frontend engineer job in Singapore\"\n\nAI: [Calls post_job]\n    → Returns: Job ID `abc123`, Apply URL\n\nAI: \"✅ Job posted! LinkedIn sync in progress...\"\n\n[AI waits 5 minutes, then checks]\n\nAI: [Calls check_linkedin_status with jobId: abc123]\n    → Returns: LinkedIn URL\n\nAI: \"🎉 LinkedIn sync complete! URL: https://linkedin.com/jobs/view/...\"\n\nProactive Check Script (for AI)\n// After post_job returns a Job ID:\nconst jobId = response.jobId;\n\n// Wait 5 minutes\nawait sleep(300000);\n\n// Check LinkedIn status\nconst result = await check_linkedin_status({ jobId });\n\n// If still pending, check every 3-5 minutes\n// When URL is available, notify user immediately\n\nSupported Locations\n\nThe skill includes a built-in location database (assets/locations.json) with 100+ cities:\n\nAsia Pacific: Singapore, Hong Kong, Beijing, Shanghai, Tokyo, Sydney, Mumbai, Bangkok, Seoul, Taipei\n\nNorth America: New York, San Francisco, Los Angeles, Seattle, Chicago, Toronto, Vancouver\n\nEurope: London, Berlin, Paris, Amsterdam, Dublin, Zurich, Stockholm\n\nMiddle East: Dubai, Abu Dhabi, Riyadh, Tel Aviv\n\nSee assets/locations.json for the complete list. Fuzzy matching supports variations like \"NYC\" → \"New York\".\n\n📦 Installation\nInstall via ClawHub\nclawhub install post-job\n\nManual Installation\n# Clone or download the skill\ncd your-openclaw-workspace/skills\n\n# Install dependencies\ncd post-job\nnpm install\n\n🔐 Security Notes\nEmail Privacy: Resume emails are visible in job postings - use a dedicated hiring email\nRate Limiting: API may have rate limits for high-volume posting\n🐛 Troubleshooting\nIssue: Job posts but no confirmation\n\nCause: Response timeout or network issue\n\nSolution: Check backend logs, verify API credentials, retry with --force\n\nIssue: City not recognized\n\nCause: City not in location database\n\nSolution:\n\nCheck assets/locations.json for supported cities\nTry alternative spelling (e.g., \"New York\" vs \"NYC\")\nAdd new city to database and republish\nIssue: Duplicate job postings\n\nCause: Multiple API calls due to retry logic\n\nSolution: Check backend for duplicate jobs, implement request deduplication\n\n❓ FAQ - Security & Privacy\n\nQ: Is my data safe with Fuku AI? A: Job data is transmitted to Fuku AI's servers for distribution. They act as a relay service. Avoid sharing confidential information in job descriptions.\n\nQ: Do I need to trust Fuku AI? A: Yes — this skill depends on their service to post jobs. Review their terms at https://hapi.fuku.ai if you have concerns.\n\nQ: Can I use this without LinkedIn sync? A: Yes — jobs are still posted to 20+ other boards. LinkedIn is optional background sync.\n\nQ: Will the job appear on MY LinkedIn company page? A: No — postings appear through Fuku AI's relay accounts, not your company's page. This is why no LinkedIn binding is required.\n\nQ: What happens if Fuku AI goes offline? A: Job posting may fail or LinkedIn sync may be delayed. The skill will return an error message.\n\nQ: Can I delete a job after posting? A: Contact Fuku AI support with your Job ID. Direct deletion through this skill is not currently supported.\n\nQ: Is the embedded credential a security risk? A: The embedded identifier is for Fuku AI's free tier access. It doesn't expose your personal credentials, but means jobs are posted under their service account.\n\nQ: Should I use this for confidential hiring? A: No — use traditional channels (internal HR systems, executive search firms) for sensitive or confidential roles.\n\n🤝 Contributing\n\nFound a bug or want to add more cities?\n\nFork the skill\nMake your changes\nTest thoroughly\nSubmit a pull request\n📝 Changelog\nv1.2.0 (Security & Transparency Update)\nAdded Security Best Practices section: Comprehensive guide for safe usage without code changes\nAdded FAQ - Security & Privacy: Answers 8 common questions about data handling, trust, and limitations\nAdded Pre-Posting Checklist: Quick verification list before submitting jobs\nEnhanced External Service Notice: Clarified LinkedIn no-binding requirement with prominent notice\nAdded .env.example: Template for OpenAI API key configuration\nUpdated Features list: Noted OpenAI-powered JD generation and no LinkedIn binding required\nDocumentation improvements: Better transparency about third-party relay model and data flow\nv1.1.11 (OpenAI Integration)\nAdded OpenAI integration: Job descriptions generated using OpenAI GPT-4o\nAdded .env configuration: Secure storage for OpenAI API key\nUpdated dependencies: Added dotenv for environment variable support\nv1.1.10 (Documentation Fix - LinkedIn Monitor)\nFixed misleading documentation: Clarified that post_job does NOT automatically monitor LinkedIn sync\nMade monitor spawning REQUIRED: Changed \"Recommended\" to \"Required\" in AI Assistant Workflow\nUpdated response format: Removed \"I'll notify you\" promise from response template\nAdded explicit warnings: Multiple ⚠️ notices explaining AI must spawn monitor sub-agent\nv1.1.9 (Security Hardening)\nEnhanced prompt injection protection with double-layer sanitization\nUser input and AI-generated content both filtered before external API calls\nv1.1.8 (Security Fix)\nAdded sanitizeDescription() function to clean job descriptions before sending to external AI\nRemoved code blocks, special markers, and common injection patterns\nAdded length limits to prevent buffer-based attacks\nv1.0.0 (Initial Release)\nCore job posting functionality\n100+ city support with fuzzy matching\nEmail validation\nLinkedIn sync integration\nError handling and validation\n📄 License\n\nThis skill is provided as-is for use with OpenClaw.\n\n🆘 Support\n\nFor issues or questions:\n\nCheck this SKILL.md for troubleshooting\nReview error messages carefully\nContact developer email yangkai31@gmail.com if you run into any issues\n\nHappy Hiring! 🎉"
  },
  "trust": {
    "sourceLabel": "tencent",
    "provenanceUrl": "https://clawhub.ai/zhangdong/post-job",
    "publisherUrl": "https://clawhub.ai/zhangdong/post-job",
    "owner": "zhangdong",
    "version": "1.2.0",
    "license": null,
    "verificationStatus": "Indexed source record"
  },
  "links": {
    "detailUrl": "https://openagent3.xyz/skills/post-job",
    "downloadUrl": "https://openagent3.xyz/downloads/post-job",
    "agentUrl": "https://openagent3.xyz/skills/post-job/agent",
    "manifestUrl": "https://openagent3.xyz/skills/post-job/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/post-job/agent.md"
  }
}