Recipes¶
Step-by-step walkthroughs for common contributions. For tooling depth (pre-commit hooks, MkDocs previews, local static analysis) see the Developer Guide.
Adding a keyword¶
Adding a method to an API class is not enough — keywords surface through six entry points. The complete walkthrough:
- Add the method to
ActionKeyword,AppManagement,Verifier, orFlowControl(optics_framework/api/). It is auto-registered for the CSV/YAML runner,optics live,optics serve,optics mcp, andoptics list. - If it locates an element, decorate it with
@with_self_healing(api/action_keyword.py) so it routes through the locator ladder (XPath → text → OCR → image), gets AOI/screenshot resilience and AI self-heal for free. The wrapped function must accept a keyword-onlylocatedparameter. - Expose it on the SDK facade: add a wrapper in
optics.py:Opticswith@keyword("Pretty Name")— without this it is invisible to Robot Framework and the public SDK. - Teach the code generator: add
"Pretty Name": "method_name"toTestFrameworkGenerator.keyword_registry(helper/generate.py), and add"Pretty Name"to thekeyword_registryset insideYAMLDataReader.read_modulesso YAML step parsing recognises multi-word names. Making this registration simpler is tracked in #484. - Write tests for it: add new test cases under
tests/units/ortests/feature/covering your keyword — running the existing suite alone is not enough, since nothing else exercises the new code path. Document the keyword too. - Verify: run
optics listand confirm reflection picks it up.
The display name ("Pretty Name") is independent of the Python method name — changing either requires touching every point above plus docs.
Adding an engine backend¶
- Driver: subclass
DriverInterfaceinengines/drivers/<name>.py; discovered by module filename matching theconfig.yamlkey. - Element source: implement
ElementSourceInterfaceinengines/elementsources/<name>.py; setREQUIRED_DRIVER_TYPEso the factory injects the matching driver. - OCR / image detector: implement
TextInterface/ImageInterfaceunderengines/vision_models/. - LLM backend: subclass
LLMInterfaceinengines/llm_models/<name>.py; selected by module filename matching thellm_models:config key.
See architecture → engines for the wiring details.