{"id":4019,"date":"2026-08-18T10:00:00","date_gmt":"2026-08-18T14:00:00","guid":{"rendered":"https:\/\/www.mymiller.name\/wordpress\/?p=4019"},"modified":"2026-08-16T08:27:51","modified_gmt":"2026-08-16T12:27:51","slug":"standard-mechanisms-for-installing-and-managing-agent-skills","status":"publish","type":"post","link":"https:\/\/www.mymiller.name\/wordpress\/spring_ai\/standard-mechanisms-for-installing-and-managing-agent-skills\/","title":{"rendered":"Standard Mechanisms for Installing and Managing Agent Skills"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">As the <strong>Agent Skills specification<\/strong> (<code>SKILL.md<\/code>) matures, managing skill lifecycles\u2014discovering, installing, updating, and sandboxing skills\u2014has settled into several standard mechanisms.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Because skills are fundamentally <strong>directory-based packages<\/strong> (containing <code>SKILL.md<\/code>, scripts, and resources), installation boils down to placing verified directory structures into an agent&#8217;s configured skills directory (typically <code>.\/skills<\/code> or <code>.agent\/skills<\/code>).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Below are the primary industry-standard mechanisms and architectural patterns for installing skills.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">1. The Specification Standard: Directory &amp; Git-Based Distribution<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The core specification treats skills as plain directories in source control. The canonical standard mechanisms for installing skills manually or in CI\/CD pipelines are:<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">A. Git Submodules (Recommended for Enterprise\/Team Repos)<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">For team environments where skill versions must be tightly controlled across developers, standard practice is to bind skill repositories as Git submodules inside the application root.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Installing a community or company skill into your project\ngit submodule add &#91;https:\/\/github.com\/org\/agent-skill-python-evaluator.bin](https:\/\/github.com\/org\/agent-skill-python-evaluator.bin) skills\/python-evaluator\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">B. Direct Git Clones (Standalone\/Local Environments)<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">For quick local additions, developers clone remote skill repositories directly into the <code>.\/skills<\/code> directory:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>git clone &#91;https:\/\/github.com\/agent-skills\/sql-optimizer.git](https:\/\/github.com\/agent-skills\/sql-optimizer.git) skills\/sql-optimizer\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">2. CLI Package Managers (<code>skills<\/code> CLI \/ Registry Tools)<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Much like <code>npm<\/code> for Node or <code>pip<\/code> for Python, command-line tooling has emerged around the <code>agentskills.io<\/code> specification to manage skill installation seamlessly.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Standard CLI tools (such as <code>skills-cli<\/code> or <code>npx @agent-skills\/cli<\/code>) allow developers and agent runtimes to pull from GitHub or registered indexes:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Add a skill from GitHub repository\nnpx agent-skills install author\/skill-name --dir .\/skills\n\n# Update installed skills\nnpx agent-skills update --all\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>What the CLI does under the hood:<\/strong><\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Downloads the repository archive or sparse-checkout.<\/li>\n\n\n\n<li>Validates the <code>SKILL.md<\/code> frontmatter schema (<code>name<\/code>, <code>description<\/code>).<\/li>\n\n\n\n<li>Verifies optional checksums or signatures.<\/li>\n\n\n\n<li>Unpacks the files into <code>.\/skills\/&lt;skill-name>\/<\/code>.<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">3. Build-Time Skill Installation via Gradle<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">In Java\/Spring AI ecosystems, you can automate skill installation and updating during your application build using <strong>Gradle<\/strong>. This ensures all developers and CI\/CD environments pull approved skill sets automatically without manual file copies.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Option A: Gradle Task for Git-Based Skills<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">You can define a Gradle task in <code>build.gradle.kts<\/code> to pull skills prior to compilation:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ build.gradle.kts\nimport java.io.File\n\ntasks.register(\"installAgentSkills\") {\n    group = \"ai-agent\"\n    description = \"Downloads required SKILL.md bundles into the application skills folder\"\n\n    val skillsDir = layout.projectDirectory.dir(\"skills\").asFile\n\n    doLast {\n        val skillRepos = mapOf(\n            \"data-analyzer\" to \"&#91;https:\/\/github.com\/my-org\/skill-data-analyzer.git](https:\/\/github.com\/my-org\/skill-data-analyzer.git)\",\n            \"pdf-parser\" to \"&#91;https:\/\/github.com\/my-org\/skill-pdf-parser.git](https:\/\/github.com\/my-org\/skill-pdf-parser.git)\"\n        )\n\n        skillRepos.forEach { (name, repoUrl) -&gt;\n            val targetFolder = File(skillsDir, name)\n            if (!targetFolder.exists()) {\n                logger.lifecycle(\"Installing skill '$name' from $repoUrl...\")\n                exec {\n                    commandLine(\"git\", \"clone\", \"--depth\", \"1\", repoUrl, targetFolder.absolutePath)\n                }\n            } else {\n                logger.lifecycle(\"Skill '$name' already installed.\")\n            }\n        }\n    }\n}\n\n\/\/ Bind skill installation before processing resources\ntasks.named(\"processResources\") {\n    dependsOn(\"installAgentSkills\")\n}\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">4. Dynamic Runtime Skill Installation (Spring AI Architecture)<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">If your AI system requires <strong>runtime skill installation<\/strong> (e.g., an admin user uploads a <code>.zip<\/code> or pastes a Git URL to grant the AI new capabilities on the fly), you can build an installer service in Spring AI.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Architectural Blueprint for a Spring AI Skill Installer Service<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>package com.example.ai.skill;\n\nimport org.eclipse.jgit.api.Git;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.stereotype.Service;\nimport org.springframework.web.multipart.MultipartFile;\n\nimport java.io.File;\nimport java.io.InputStream;\nimport java.nio.file.*;\nimport java.util.zip.ZipEntry;\nimport java.util.zip.ZipInputStream;\n\n@Service\npublic class SkillInstallerService {\n\n    private final Path rootSkillsDir;\n    private final SkillRegistry skillRegistry;\n\n    public SkillInstallerService(\n            @Value(\"${app.skills.directory:.\/skills}\") String skillsDir,\n            SkillRegistry skillRegistry) {\n        this.rootSkillsDir = Paths.get(skillsDir).toAbsolutePath();\n        this.skillRegistry = skillRegistry;\n    }\n\n    \/**\n     * Installs a skill directly from a remote Git repository at runtime.\n     *\/\n    public void installFromGit(String gitUrl, String skillFolderName) throws Exception {\n        Path targetDir = rootSkillsDir.resolve(skillFolderName).normalize();\n\n        if (Files.exists(targetDir)) {\n            throw new IllegalArgumentException(\"Skill already installed at target location\");\n        }\n\n        \/\/ Clone repository (using JGit library or ProcessBuilder)\n        try (Git git = Git.cloneRepository()\n                .setURI(gitUrl)\n                .setDirectory(targetDir.toFile())\n                .setDepth(1)\n                .call()) {\n            \n            \/\/ Validate SKILL.md exists\n            validateSkillStructure(targetDir);\n            \n            \/\/ Reload Spring AI Registry\n            skillRegistry.refresh();\n        }\n    }\n\n    \/**\n     * Installs a skill from an uploaded ZIP archive.\n     *\/\n    public void installFromZip(MultipartFile file) throws Exception {\n        try (InputStream is = file.getInputStream();\n             ZipInputStream zis = new ZipInputStream(is)) {\n            \n            ZipEntry entry;\n            while ((entry = zis.getNextEntry()) != null) {\n                Path newPath = zipSlipProtect(entry, rootSkillsDir);\n                if (entry.isDirectory()) {\n                    Files.createDirectories(newPath);\n                } else {\n                    Files.createDirectories(newPath.getParent());\n                    Files.copy(zis, newPath, StandardCopyOption.REPLACE_EXISTING);\n                }\n                zis.closeEntry();\n            }\n        }\n        \n        \/\/ Refresh Spring AI Registry to pick up the new skill\n        skillRegistry.refresh();\n    }\n\n    private void validateSkillStructure(Path skillDir) {\n        if (!Files.exists(skillDir.resolve(\"SKILL.md\"))) {\n            \/\/ Rollback\/delete dir if invalid\n            FileSystemUtils.deleteRecursively(skillDir.toFile());\n            throw new IllegalStateException(\"Invalid Skill: Missing SKILL.md manifest\");\n        }\n    }\n\n    private Path zipSlipProtect(ZipEntry entry, Path targetDir) {\n        Path resolved = targetDir.resolve(entry.getName()).normalize();\n        if (!resolved.startsWith(targetDir)) {\n            throw new SecurityException(\"Bad zip entry (Zip Slip vulnerability detected): \" + entry.getName());\n        }\n        return resolved;\n    }\n}\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">5. Security Architecture for Installing Remote Skills<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">When allowing skill installation (especially skills that execute python or shell scripts), follow these security mandates:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Manifest Validation:<\/strong> Ensure mandatory frontmatter fields exist before registering the skill.<\/li>\n\n\n\n<li><strong>Zip Slip \/ Path Traversal Prevention:<\/strong> When extracting zip archives or resolving git subtrees, strictly verify that paths cannot write outside <code>.\/skills\/<\/code>.<\/li>\n\n\n\n<li><strong>Execution Permissions:<\/strong> Python scripts inside installed skills should be explicitly set to read-only for application runtimes, executing with unprivileged OS users.<\/li>\n\n\n\n<li><strong>Environment Isolation:<\/strong> For production environments running user-installed Python scripts, execute the skill scripts inside ephemeral Docker containers or restricted sandboxes rather than directly on the host JVM process.<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">Summary<\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td><strong>Mechanism<\/strong><\/td><td><strong>Ideal Use Case<\/strong><\/td><td><strong>Tooling \/ Command<\/strong><\/td><\/tr><tr><td><strong>Git Submodules<\/strong><\/td><td>Core team projects, strict versioning<\/td><td><code>git submodule add &lt;repo&gt; skills\/&lt;name&gt;<\/code><\/td><\/tr><tr><td><strong>Skill CLI<\/strong><\/td><td>Local developer tooling, fast prototyping<\/td><td><code>npx agent-skills install &lt;repo&gt;<\/code><\/td><\/tr><tr><td><strong>Gradle Tasks<\/strong><\/td><td>Automated Java\/Spring build pipelines<\/td><td>Custom Gradle <code>git clone<\/code> or HTTP task<\/td><\/tr><tr><td><strong>Runtime Installer<\/strong><\/td><td>Admin\/User-driven plugin management in Spring AI<\/td><td>JGit \/ Zip upload REST endpoints<\/td><\/tr><\/tbody><\/table><\/figure>\n","protected":false},"excerpt":{"rendered":"<p>As the Agent Skills specification (SKILL.md) matures, managing skill lifecycles\u2014discovering, installing, updating, and sandboxing skills\u2014has settled into several standard mechanisms. Because skills are fundamentally directory-based packages (containing SKILL.md, scripts, and resources), installation boils down to placing verified directory structures into an agent&#8217;s configured skills directory (typically .\/skills or .agent\/skills). Below are the primary industry-standard mechanisms [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":4024,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_coblocks_attr":"","_coblocks_dimensions":"","_coblocks_responsive_height":"","_coblocks_accordion_ie_support":"","_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2},"jetpack_post_was_ever_published":false},"categories":[495,443],"tags":[],"series":[],"class_list":["post-4019","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-ai","category-spring_ai"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2026\/08\/1786883167765.avif","jetpack-related-posts":[{"id":4017,"url":"https:\/\/www.mymiller.name\/wordpress\/spring_ai\/extending-spring-ai-with-agent-skills-executing-python-scripts-via-skill-md\/","url_meta":{"origin":4019,"position":0},"title":"Extending Spring AI with Agent Skills: Executing Python Scripts via SKILL.md","author":"Jeffery Miller","date":"August 17, 2026","format":false,"excerpt":"As AI agents evolve from simple chat interfaces to autonomous problem-solving systems, managing prompt bloat and custom tool integrations becomes a critical architectural challenge. If you embed every instruction, workflow, and script binding directly into system prompts, your model context windows quickly saturate, token costs soar, and agent behavior becomes\u2026","rel":"","context":"In &quot;AI&quot;","block_context":{"text":"AI","link":"https:\/\/www.mymiller.name\/wordpress\/category\/ai\/"},"img":{"alt_text":"","src":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2026\/08\/1786883002818.avif","width":350,"height":200,"srcset":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2026\/08\/1786883002818.avif 1x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2026\/08\/1786883002818.avif 1.5x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2026\/08\/1786883002818.avif 2x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2026\/08\/1786883002818.avif 3x"},"classes":[]},{"id":3080,"url":"https:\/\/www.mymiller.name\/wordpress\/misc\/multi-directory-git\/","url_meta":{"origin":4019,"position":1},"title":"Multi-Directory GIT","author":"Jeffery Miller","date":"July 28, 2026","format":false,"excerpt":"You may or may not find this useful. I work with a my GIT repositories all at the same level. I like to keep them in sync. However going to each repository and repeating the commands is a pain. So I created the following shell script to make my life\u2026","rel":"","context":"In &quot;Miscellaneous&quot;","block_context":{"text":"Miscellaneous","link":"https:\/\/www.mymiller.name\/wordpress\/category\/misc\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":2676,"url":"https:\/\/www.mymiller.name\/wordpress\/app\/linux-desktop-on-windows-10\/","url_meta":{"origin":4019,"position":2},"title":"Linux Desktop on Windows 10","author":"Jeffery Miller","date":"September 13, 2021","format":false,"excerpt":"Enabled Windows Subsystem for Linux First step is to make sure you have Windows 10 Fall Creators Update installed. This can be found here. Complete this update then search for Ubuntu in the Microsoft Store. I recommend Ubuntu 18.04 LTS, as this will be supported for a number of years\u2026","rel":"","context":"In &quot;Technology&quot;","block_context":{"text":"Technology","link":"https:\/\/www.mymiller.name\/wordpress\/category\/app\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2020\/02\/computer-4674946_640.jpg?fit=640%2C480&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2020\/02\/computer-4674946_640.jpg?fit=640%2C480&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2020\/02\/computer-4674946_640.jpg?fit=640%2C480&ssl=1&resize=525%2C300 1.5x"},"classes":[]},{"id":2511,"url":"https:\/\/www.mymiller.name\/wordpress\/angular\/angular-environment\/","url_meta":{"origin":4019,"position":3},"title":"Angular Environment","author":"Jeffery Miller","date":"March 11, 2019","format":false,"excerpt":"Building a website for today and tomorrow begins with Angular. Yes I am a proponent of Angular over many other client frameworks. Let's look over the goals of this post to help you get started. Node.jsAngular-CliAngular Workspace Angular Material Installing Node.js First step you need to do is to install\u2026","rel":"","context":"In &quot;Angular&quot;","block_context":{"text":"Angular","link":"https:\/\/www.mymiller.name\/wordpress\/category\/angular\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2019\/03\/geometry-1023846_640.jpg?fit=640%2C359&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2019\/03\/geometry-1023846_640.jpg?fit=640%2C359&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2019\/03\/geometry-1023846_640.jpg?fit=640%2C359&ssl=1&resize=525%2C300 1.5x"},"classes":[]},{"id":4004,"url":"https:\/\/www.mymiller.name\/wordpress\/ai\/the-complete-guide-to-modern-ai-terminology-from-neural-networks-to-rag-mcp-and-agentic-systems\/","url_meta":{"origin":4019,"position":4},"title":"The Complete Guide to Modern AI Terminology: From Neural Networks to RAG, MCP, and Agentic Systems","author":"Jeffery Miller","date":"July 29, 2026","format":false,"excerpt":"Artificial Intelligence is evolving rapidly, bringing with it a wave of new concepts, acronyms, and technical jargon. Whether you are building AI applications, reading tech news, or evaluating tools for work, understanding this vocabulary is essential. This guide breaks down modern AI terminology into logical categories\u2014from foundational computer science principles\u2026","rel":"","context":"In &quot;AI&quot;","block_context":{"text":"AI","link":"https:\/\/www.mymiller.name\/wordpress\/category\/ai\/"},"img":{"alt_text":"","src":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2026\/07\/Gemini_Generated_Image_t8nujmt8nujmt8nu-scaled.avif","width":350,"height":200,"srcset":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2026\/07\/Gemini_Generated_Image_t8nujmt8nujmt8nu-scaled.avif 1x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2026\/07\/Gemini_Generated_Image_t8nujmt8nujmt8nu-scaled.avif 1.5x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2026\/07\/Gemini_Generated_Image_t8nujmt8nujmt8nu-scaled.avif 2x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2026\/07\/Gemini_Generated_Image_t8nujmt8nujmt8nu-scaled.avif 3x"},"classes":[]},{"id":3834,"url":"https:\/\/www.mymiller.name\/wordpress\/spring_rest\/documenting-your-datas-reach-generating-api-docs-for-spring-data-rest\/","url_meta":{"origin":4019,"position":5},"title":"Documenting Your Data&#8217;s Reach: Generating API Docs for Spring Data REST","author":"Jeffery Miller","date":"December 24, 2025","format":false,"excerpt":"Spring Data REST is a fantastic tool for rapidly exposing your JPA entities as hypermedia-driven REST APIs. However, even the most intuitive APIs benefit from clear and comprehensive documentation. While HATEOAS provides discoverability at runtime, static documentation offers a bird\u2019s-eye view, making it easier for developers to understand the API\u2019s\u2026","rel":"","context":"In &quot;Spring Rest&quot;","block_context":{"text":"Spring Rest","link":"https:\/\/www.mymiller.name\/wordpress\/category\/spring_rest\/"},"img":{"alt_text":"","src":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/10\/network-5987786_1280-jpg.avif","width":350,"height":200,"srcset":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/10\/network-5987786_1280-jpg.avif 1x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/10\/network-5987786_1280-jpg.avif 1.5x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/10\/network-5987786_1280-jpg.avif 2x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/10\/network-5987786_1280-jpg.avif 3x"},"classes":[]}],"jetpack_sharing_enabled":true,"jetpack_likes_enabled":true,"_links":{"self":[{"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/posts\/4019","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/comments?post=4019"}],"version-history":[{"count":1,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/posts\/4019\/revisions"}],"predecessor-version":[{"id":4020,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/posts\/4019\/revisions\/4020"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/media\/4024"}],"wp:attachment":[{"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/media?parent=4019"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/categories?post=4019"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/tags?post=4019"},{"taxonomy":"series","embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/series?post=4019"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}