Elementor V4 atomic widget development patterns for Vikingo plugins. MUST be applied when creating or modifying Elementor widgets, dynamic tags, or editor previews in any Vikingo WordPress plugin — the atomic API (Elementor\Modules\AtomicWidgets) is undocumented and internal, so this skill captures the proven guard patterns (class_exists + experiment check + try/catch), the widget anatomy (define_props_schema, define_atomic_controls, get_atomic_settings computing rendered_html server-side), the Twig template contract, the REST-based live editor preview hydration, prop/control type reference, the post-Elementor-update checklist, and known pitfalls. Triggers on Elementor widget, atomic widget, Atomic_Widget_Base, twig template, dynamic tag, editor preview, e_atomic_elements, Elementor V4, or any vk- plugin Elementor integration.
A V4 atomic API (Elementor\Modules\AtomicWidgets\*) BELSŐ, nem dokumentált és
experiment mögött él. Ez a skill a három élesben bizonyított Vikingo
implementáció (vk-tematika, vk-ajanlas, vikingo-bunny-video) desztillált
tudása. Az itteni minták kötelezők minden új Vikingo atomic widgetnél.
0. Alapelvek
Minden Elementor-érintés guard mögött. Ha az API változik vagy hiányzik,
a widget csendben nem regisztrálódik; az oldal nem törhet el.
Mindig van shortcode-tartalék. A render logika Elementor-független
osztályban él (Frontend/Renderer minta), a widget és a shortcode ugyanazt
hívja. Elementor nélkül is mindennek működnie kell.
A HTML szerveroldalon készül. A twig sablon csak beilleszti a kész
rendered_html-t; a szerkesztői vászonra REST-hidratálás hozza az élő képet.
A referencia-repók verzióját Elementor-frissítéskor cserélni kell, és utána a
9. pont ellenőrzőlistáját végigfutni. (Utolsó ismert állapot: 4.2.1.)
2. Regisztráció és guardok
A belépési pont egy Elementor/Module osztály, amit a Plugin csak akkor hív,
ha egyáltalán van Elementor. A minta:
public static function register(): void {
// Atomic widgetek: csak ha a V4 atomic alaposztály elérhető.
if ( class_exists( \Elementor\Modules\AtomicWidgets\Elements\Base\Atomic_Widget_Base::class ) ) {
add_filter(
'elementor/widgets/register',
static function ( $widgets_manager ) {
$widgets_manager->register( new Widgets\SajatWidget() );
return $widgets_manager;
}
);
}
}
Szigorúbb környezetben (ha klasszikus fallback widget is van, mint a bunny-nál)
a teljes ellenőrzés: minden HASZNÁLT osztályra class_exists (alaposztály,
minden control, minden prop type), PLUSZ az experiment:
és a $widgets_manager->register() hívás try/catch (\Throwable) blokkban,
hogy egy Elementor-frissítés okozta törés soha ne legyen fatal, csak fallback.
3. A widget anatómiája
class SajatWidget extends Atomic_Widget_Base {
use Has_Template;
// Saját újradeklarálás, különben a közös ős STATIKUS property-jét írnánk,
// és két Vikingo widget egymás leírását mutatná.
public static $widget_description = null;
public function __construct( $data = array(), $args = null ) {
static::$widget_description = __( 'Leírás…', 'vk-plugin' );
parent::__construct( $data, $args );
}
public static function get_element_type(): string {
return 'vk-sajat'; // ez kerül az Elementor oldal-JSON-ba: SOHA nem változhat!
}
protected static function define_props_schema(): array { /* STATIKUS! */ }
protected function define_atomic_controls(): array { /* Section-ök */ }
public function get_atomic_settings(): array {
$settings = parent::get_atomic_settings();
// A HTML-t ITT számoljuk szerveroldalon; a mellékhatások (asset enqueue,
// JSON-LD regisztráció) is itt indulnak, mert a twig-ben már késő.
$settings['rendered_html'] = $this->render_html( $settings );
return $settings;
}
protected function get_templates(): array {
return array( 'vikingo/sajat' => VK_X_PATH . 'assets/twig/sajat.html.twig' );
}
}
Kritikus tudnivalók:
get_element_type() értéke bekerül minden Elementor oldal adatai közé.
Átnevezése az összes meglévő oldalon eltünteti a widgetet. Refaktornál,
plugin-összevonásnál a widget-név VÁLTOZATLAN marad.
define_props_schema() statikus, ezért a közös prop-készletet is statikus
metódusban add tovább (common_props_schema() minta az ajanlas
AbstractTestimonialWidget-jében).
A classes prop kötelező eleme a sémának:
'classes' => Classes_Prop_Type::make()->default( array() ).
A Has_Template::render() a kivételeket lenyeli (csak ELEMENTOR_DEBUG
mellett dobja tovább) — némán üres widget = valószínűleg twig- vagy
kontextushiba, debug módban derül ki.
A controlok Section::make()->set_label()->set_id()->set_items([...])
szekciókba rendezve mennek, Xxx_Control::bind_to( 'prop_nev' ) kötéssel.
Dinamikus tartalom-választáshoz (pl. CPT bejegyzések) létezik Query_Control
(set_query_config()), de a bevált Vikingo minta az egyszerű
Select_Control + saját options-forrás (lásd tematika CourseOptions).
5. A twig sablon szerződése
A Has_Template::render() kontextusa: id, interaction_id, type,
settings, base_styles. A Vikingo sablon-minta:
{% set classes = settings.classes | default([]) | join(' ') %}
<div data-id="{{ id }}" data-e-type="{{ type }}" class="{{ classes }}"
data-vk-course="{{ settings.course }}">
{% if settings.rendered_html is defined and settings.rendered_html %}
{{ settings.rendered_html | raw }}
{% else %}
<div style="border:1px dashed #FF544D;…">Vikingo X – előnézet betöltése…</div>
{% endif %}
</div>
A sablon CSAK beilleszt (| raw), logika nincs benne.
Minden beállítás, amit az előnézetnek látnia kell, data-vk-* attribútumként
is kikerül — ebből dolgozik a hidratáló JS.
A helyettesítő doboz azért kell, mert a szerkesztőben a twig KLIENS oldalon
fut, ahol a rendered_html nem létezik.
6. Szerkesztői élő előnézet (REST-hidratálás)
A szerkesztő vásznán a twig kliens oldalon fut, a szerveroldali
rendered_html ott nem érhető el. A bevált megoldás három elem:
REST végpont (vikingo/v1/{plugin}/render, GET, publikus — ugyanazt a
HTML-t adja, ami a frontenden is megjelenik): a paraméterekből lerendereli
a widgetet és { html: … }-t ad vissza.
Preview enqueue: az elementor/preview/enqueue_styles és
…/enqueue_scripts hookon betöltjük a frontend CSS/JS-t és az
editor-preview.js-t, wp_add_inline_script-tel átadva a REST URL-t.
editor-preview.js: MutationObserver figyeli a vásznat (250 ms
debounce), a [data-e-type="vk-…"] elemeket a data-vk-* attribútumokból
épített query-vel hidratálja. A lekért query-t data-vk-hydrated-ben
tárolja, így változatlan beállításnál nincs újabb fetch. Hidratálás után
meghívja a frontend init függvényt (window.vkXInit), hogy az interakciók
a vásznon is éljenek.
Teljes referencia: tematika assets/js/editor-preview.js +
src/Rest/RenderController.php + src/Elementor/Module.php.
7. Dynamic tag (stabil API, nem atomic)
A dynamic tag a RÉGI, dokumentált API-ra épül (Elementor\Core\DynamicTags\Tag),
guard: class_exists( \Elementor\Core\DynamicTags\Tag::class ), regisztráció az
elementor/dynamic_tags/register hookon. A tag alap az ingyenes Elementorban
van, a beszúró felület a Pro-ban. Controlok a klasszikus
Controls_Manager::SELECT stílusban. Minta: tematika TematikaAdatTag.
8. CSS az Elementor kit ellen
Az Elementor kit globális button/h2/p stílusai felülírják a widget CSS-ét.
Vikingo szabály: minden szabály a widget gyökérosztályával prefixelve
(.vk-x .vk-x-gomb — dupla osztály-specificitás) és explicit resetekkel.
Tokenek: --vkx-* lokális változók var(--vk-*, fallback) értékkel, hogy az
oldal design systeme felülbírálhasson. JSON-LD SOHA nem a widget kimenetébe
megy, hanem wp_footer-be, mert az Elementor content pipeline megrongálhatja.
9. Elementor-frissítés utáni ellenőrzőlista
Frissítéskor a referencia-repókat lecserélni, majd ellenőrizni:
Atomic_Widget_Base és Has_Template létezik-e még ugyanazon a néven
(elements/base/), változott-e a konstruktor vagy az absztrakt metódusok.
A Has_Template::render() twig kontextus-kulcsai változatlanok-e
(id, interaction_id, type, settings, base_styles).
A használt controlok (Select_Control::set_options formátum!) és prop
típusok megvannak-e.
Az e_atomic_elements experiment neve/állapota változott-e
(modules/atomic-widgets/module.php, EXPERIMENT_NAME).
Éles teszt: widget behúzása a szerkesztőben, beállítás-változtatás
(hidratálás frissül-e), mentés, frontend render, shortcode render.
Widget-név = adat.get_element_type() átnevezése minden meglévő
oldalról törli a widgetet. Összevonásnál, átnevezésnél tilos hozzányúlni.
$widget_description statikus és közös — minden widgetben újra kell
deklarálni, különben az utoljára konstruált widget leírása jelenik meg
mindenhol.
A define_props_schema() statikus, nem fér hozzá $this-hez; a
dinamikus alapértékek (pl. fordított stringek) mehetnek bele, de
példány-állapot nem.
Mellékhatások helye a get_atomic_settings() (asset enqueue, schema):
a render()-t a Has_Template adja, oda nem nyúlunk bele.
A szerkesztői vászon nem futtat PHP-t — bármi, ami a frontenden PHP-ból
jön, a vásznon csak REST-hidratálással jelenik meg.
Üres widget a frontenden, hiba nélkül: a Has_Template::render()
try/catch-e nyelte le — ELEMENTOR_DEBUG mellett újratesztelni.
File:// alapú headless Chrome teszt megbízhatatlan — vizuális
ellenőrzéshez mindig php -S szerver + Playwright (channel: chrome).
1---2name: vikingo-elementor-atomic3description: Elementor V4 atomic widget development patterns for Vikingo plugins. MUST be applied when creating or modifying Elementor widgets, dynamic tags, or editor previews in any Vikingo WordPress plugin — the atomic API (Elementor\Modules\AtomicWidgets) is undocumented and internal, so this skill captures the proven guard patterns (class_exists + experiment check + try/catch), the widget anatomy (define_props_schema, define_atomic_controls, get_atomic_settings computing rendered_html server-side), the Twig template contract, the REST-based live editor preview hydration, prop/control type reference, the post-Elementor-update checklist, and known pitfalls. Triggers on Elementor widget, atomic widget, Atomic_Widget_Base, twig template, dynamic tag, editor preview, e_atomic_elements, Elementor V4, or any vk- plugin Elementor integration.4---56# Vikingo – Elementor V4 atomic widget minták78A V4 atomic API (`Elementor\Modules\AtomicWidgets\*`) BELSŐ, nem dokumentált és9experiment mögött él. Ez a skill a három élesben bizonyított Vikingo10implementáció (vk-tematika, vk-ajanlas, vikingo-bunny-video) desztillált11tudása. Az itteni minták kötelezők minden új Vikingo atomic widgetnél.1213## 0. Alapelvek1415- **Minden Elementor-érintés guard mögött.** Ha az API változik vagy hiányzik,16 a widget csendben nem regisztrálódik; az oldal nem törhet el.17- **Mindig van shortcode-tartalék.** A render logika Elementor-független18 osztályban él (`Frontend/Renderer` minta), a widget és a shortcode ugyanazt19 hívja. Elementor nélkül is mindennek működnie kell.20- **A HTML szerveroldalon készül.** A twig sablon csak beilleszti a kész21 `rendered_html`-t; a szerkesztői vászonra REST-hidratálás hozza az élő képet.2223## 1. Referencia-források (helyi gépen)2425| Mi | Hol |26|---|---|27| Elementor teljes forrás | `~/Documents/Github/reference-elementor/` |28| Elementor Pro teljes forrás | `~/Documents/Github/reference-elementor-pro/` |29| Atomic alaposztály | `reference-elementor/modules/atomic-widgets/elements/base/atomic-widget-base.php` |30| Has_Template trait (render + twig kontextus) | `.../elements/base/has-template.php` |31| Core minta-widget | `reference-elementor/modules/atomic-widgets/elements/atomic-youtube/` |32| Control típusok | `reference-elementor/modules/atomic-widgets/controls/types/` |33| Prop típusok | `reference-elementor/modules/atomic-widgets/prop-types/` |34| Működő Vikingo minták | `wp-plugin-vikingo-hu-tematika/src/Elementor/`, `wp-plugin-vikingo-ajanlas/src/Elementor/` |3536A referencia-repók verzióját Elementor-frissítéskor cserélni kell, és utána a379. pont ellenőrzőlistáját végigfutni. (Utolsó ismert állapot: 4.2.1.)3839## 2. Regisztráció és guardok4041A belépési pont egy `Elementor/Module` osztály, amit a Plugin csak akkor hív,42ha egyáltalán van Elementor. A minta:4344```php45public static function register(): void {46 // Atomic widgetek: csak ha a V4 atomic alaposztály elérhető.47 if ( class_exists( \Elementor\Modules\AtomicWidgets\Elements\Base\Atomic_Widget_Base::class ) ) {48 add_filter(49 'elementor/widgets/register',50 static function ( $widgets_manager ) {51 $widgets_manager->register( new Widgets\SajatWidget() );52 return $widgets_manager;53 }54 );55 }56}57```5859Szigorúbb környezetben (ha klasszikus fallback widget is van, mint a bunny-nál)60a teljes ellenőrzés: minden HASZNÁLT osztályra `class_exists` (alaposztály,61minden control, minden prop type), PLUSZ az experiment:6263```php64$experiments = \Elementor\Plugin::$instance->experiments;65$atomic_ok = $experiments && $experiments->is_feature_active( 'e_atomic_elements' );66```6768és a `$widgets_manager->register()` hívás `try/catch (\Throwable)` blokkban,69hogy egy Elementor-frissítés okozta törés soha ne legyen fatal, csak fallback.7071## 3. A widget anatómiája7273```php74class SajatWidget extends Atomic_Widget_Base {75 use Has_Template;7677 // Saját újradeklarálás, különben a közös ős STATIKUS property-jét írnánk,78 // és két Vikingo widget egymás leírását mutatná.79 public static $widget_description = null;8081 public function __construct( $data = array(), $args = null ) {82 static::$widget_description = __( 'Leírás…', 'vk-plugin' );83 parent::__construct( $data, $args );84 }8586 public static function get_element_type(): string {87 return 'vk-sajat'; // ez kerül az Elementor oldal-JSON-ba: SOHA nem változhat!88 }8990 protected static function define_props_schema(): array { /* STATIKUS! */ }91 protected function define_atomic_controls(): array { /* Section-ök */ }9293 public function get_atomic_settings(): array {94 $settings = parent::get_atomic_settings();95 // A HTML-t ITT számoljuk szerveroldalon; a mellékhatások (asset enqueue,96 // JSON-LD regisztráció) is itt indulnak, mert a twig-ben már késő.97 $settings['rendered_html'] = $this->render_html( $settings );98 return $settings;99 }100101 protected function get_templates(): array {102 return array( 'vikingo/sajat' => VK_X_PATH . 'assets/twig/sajat.html.twig' );103 }104}105```106107Kritikus tudnivalók:108109- **`get_element_type()` értéke bekerül minden Elementor oldal adatai közé.**110 Átnevezése az összes meglévő oldalon eltünteti a widgetet. Refaktornál,111 plugin-összevonásnál a widget-név VÁLTOZATLAN marad.112- **`define_props_schema()` statikus**, ezért a közös prop-készletet is statikus113 metódusban add tovább (`common_props_schema()` minta az ajanlas114 `AbstractTestimonialWidget`-jében).115- A `classes` prop kötelező eleme a sémának:116 `'classes' => Classes_Prop_Type::make()->default( array() )`.117- A `Has_Template::render()` a kivételeket lenyeli (csak `ELEMENTOR_DEBUG`118 mellett dobja tovább) — némán üres widget = valószínűleg twig- vagy119 kontextushiba, debug módban derül ki.120121## 4. Prop típusok és controlok (a használt készlet)122123| Prop type (`PropTypes\…`) | Control (`Controls\Types\…`) | Megjegyzés |124|---|---|---|125| `Primitives\String_Prop_Type` | `Text_Control`, `Textarea_Control`, `Select_Control` | `->enum([...])` a select értékkészletéhez |126| `Primitives\Boolean_Prop_Type` | `Switch_Control` | |127| `Primitives\Number_Prop_Type` | `Number_Control` | |128| `Image_Prop_Type` | `Image_Control` | médiatár-választó |129| `Link_Prop_Type` | `Link_Control` | |130| `Classes_Prop_Type` | – | kötelező, az Elementor kezeli |131132- `Select_Control::set_options()` formátuma:133 `array( array( 'value' => 'x', 'label' => 'X' ), … )` — NEM kulcs=>érték!134- A controlok `Section::make()->set_label()->set_id()->set_items([...])`135 szekciókba rendezve mennek, `Xxx_Control::bind_to( 'prop_nev' )` kötéssel.136- Dinamikus tartalom-választáshoz (pl. CPT bejegyzések) létezik `Query_Control`137 (`set_query_config()`), de a bevált Vikingo minta az egyszerű138 `Select_Control` + saját options-forrás (lásd tematika `CourseOptions`).139140## 5. A twig sablon szerződése141142A `Has_Template::render()` kontextusa: `id`, `interaction_id`, `type`,143`settings`, `base_styles`. A Vikingo sablon-minta:144145```twig146{% set classes = settings.classes | default([]) | join(' ') %}147<div data-id="{{ id }}" data-e-type="{{ type }}" class="{{ classes }}"148 data-vk-course="{{ settings.course }}">149{% if settings.rendered_html is defined and settings.rendered_html %}150{{ settings.rendered_html | raw }}151{% else %}152<div style="border:1px dashed #FF544D;…">Vikingo X – előnézet betöltése…</div>153{% endif %}154</div>155```156157- A sablon CSAK beilleszt (`| raw`), logika nincs benne.158- Minden beállítás, amit az előnézetnek látnia kell, `data-vk-*` attribútumként159 is kikerül — ebből dolgozik a hidratáló JS.160- A helyettesítő doboz azért kell, mert a szerkesztőben a twig KLIENS oldalon161 fut, ahol a `rendered_html` nem létezik.162163## 6. Szerkesztői élő előnézet (REST-hidratálás)164165A szerkesztő vásznán a twig kliens oldalon fut, a szerveroldali166`rendered_html` ott nem érhető el. A bevált megoldás három elem:1671681. **REST végpont** (`vikingo/v1/{plugin}/render`, GET, publikus — ugyanazt a169 HTML-t adja, ami a frontenden is megjelenik): a paraméterekből lerendereli170 a widgetet és `{ html: … }`-t ad vissza.1712. **Preview enqueue**: az `elementor/preview/enqueue_styles` és172 `…/enqueue_scripts` hookon betöltjük a frontend CSS/JS-t és az173 `editor-preview.js`-t, `wp_add_inline_script`-tel átadva a REST URL-t.1743. **editor-preview.js**: `MutationObserver` figyeli a vásznat (250 ms175 debounce), a `[data-e-type="vk-…"]` elemeket a `data-vk-*` attribútumokból176 épített query-vel hidratálja. A lekért query-t `data-vk-hydrated`-ben177 tárolja, így változatlan beállításnál nincs újabb fetch. Hidratálás után178 meghívja a frontend init függvényt (`window.vkXInit`), hogy az interakciók179 a vásznon is éljenek.180181Teljes referencia: tematika `assets/js/editor-preview.js` +182`src/Rest/RenderController.php` + `src/Elementor/Module.php`.183184## 7. Dynamic tag (stabil API, nem atomic)185186A dynamic tag a RÉGI, dokumentált API-ra épül (`Elementor\Core\DynamicTags\Tag`),187guard: `class_exists( \Elementor\Core\DynamicTags\Tag::class )`, regisztráció az188`elementor/dynamic_tags/register` hookon. A tag alap az ingyenes Elementorban189van, a beszúró felület a Pro-ban. Controlok a klasszikus190`Controls_Manager::SELECT` stílusban. Minta: tematika `TematikaAdatTag`.191192## 8. CSS az Elementor kit ellen193194Az Elementor kit globális button/h2/p stílusai felülírják a widget CSS-ét.195Vikingo szabály: minden szabály a widget gyökérosztályával prefixelve196(`.vk-x .vk-x-gomb` — dupla osztály-specificitás) és explicit resetekkel.197Tokenek: `--vkx-*` lokális változók `var(--vk-*, fallback)` értékkel, hogy az198oldal design systeme felülbírálhasson. JSON-LD SOHA nem a widget kimenetébe199megy, hanem `wp_footer`-be, mert az Elementor content pipeline megrongálhatja.200201## 9. Elementor-frissítés utáni ellenőrzőlista202203Frissítéskor a referencia-repókat lecserélni, majd ellenőrizni:204205- [ ] `Atomic_Widget_Base` és `Has_Template` létezik-e még ugyanazon a néven206 (`elements/base/`), változott-e a konstruktor vagy az absztrakt metódusok.207- [ ] A `Has_Template::render()` twig kontextus-kulcsai változatlanok-e208 (`id`, `interaction_id`, `type`, `settings`, `base_styles`).209- [ ] A használt controlok (`Select_Control::set_options` formátum!) és prop210 típusok megvannak-e.211- [ ] Az `e_atomic_elements` experiment neve/állapota változott-e212 (`modules/atomic-widgets/module.php`, `EXPERIMENT_NAME`).213- [ ] Éles teszt: widget behúzása a szerkesztőben, beállítás-változtatás214 (hidratálás frissül-e), mentés, frontend render, shortcode render.215- [ ] `ELEMENTOR_DEBUG` bekapcsolásával nincs-e lenyelt twig-kivétel.216217## 10. Ismert buktatók218219- **Widget-név = adat.** `get_element_type()` átnevezése minden meglévő220 oldalról törli a widgetet. Összevonásnál, átnevezésnél tilos hozzányúlni.221- **`$widget_description` statikus és közös** — minden widgetben újra kell222 deklarálni, különben az utoljára konstruált widget leírása jelenik meg223 mindenhol.224- **A `define_props_schema()` statikus**, nem fér hozzá `$this`-hez; a225 dinamikus alapértékek (pl. fordított stringek) mehetnek bele, de226 példány-állapot nem.227- **Mellékhatások helye a `get_atomic_settings()`** (asset enqueue, schema):228 a `render()`-t a `Has_Template` adja, oda nem nyúlunk bele.229- **A szerkesztői vászon nem futtat PHP-t** — bármi, ami a frontenden PHP-ból230 jön, a vásznon csak REST-hidratálással jelenik meg.231- **Üres widget a frontenden, hiba nélkül**: a `Has_Template::render()`232 try/catch-e nyelte le — `ELEMENTOR_DEBUG` mellett újratesztelni.233- **File:// alapú headless Chrome teszt megbízhatatlan** — vizuális234 ellenőrzéshez mindig `php -S` szerver + Playwright (channel: chrome).
Run npx skillmds add vikingokft/vikingo-elementor-atomic in your terminal (requires Node.js), paste this page's agent-chat prompt into Claude, Cursor, or any MCP-connected agent, or download the SKILL.md file and copy it into your agent's skills directory.
Elementor V4 atomic widget development patterns for Vikingo plugins. MUST be applied when creating or modifying Elementor widgets, dynamic tags, or editor previews in any Vikingo WordPress plugin — the atomic API (Elementor\Modules\AtomicWidgets) is undocumented and internal, so this skill captures the proven guard patterns (class_exists + experiment check + try/catch), the widget anatomy (define_props_schema, define_atomic_controls, get_atomic_settings computing rendered_html server-side), the Twig template contract, the REST-based live editor preview hydration, prop/control type reference, the post-Elementor-update checklist, and known pitfalls. Triggers on Elementor widget, atomic widget, Atomic_Widget_Base, twig template, dynamic tag, editor preview, e_atomic_elements, Elementor V4, or any vk- plugin Elementor integration. It is listed under Integrations & APIs on SkillMD.
This skill has not completed SkillMD's automated safety review yet. Capability flags: makes network calls. SkillMD never runs a skill's scripts for you; review the SKILL.md before installing.
This skill is tagged as working with Claude Code, Claude.ai, OpenAI Codex. SKILL.md is an open format, so most agents that read a skills directory can load it too.
Yes. Installing skills from SkillMD is free, and the skill stays under its author's original license.
vikingokft (@vikingokft) published this skill. Their other Agent Skills are listed on their SkillMD profile.