-
Notifications
You must be signed in to change notification settings - Fork 193
Add AgentSkills language for AI agent skill files #1336
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
Introduces a new `agent-skills` SDK language that generates 16 markdown
skill files (one per supported SDK language) teaching AI agents how to
use each Appwrite SDK. Each skill file is output as `{lang}/SKILL.md`
with YAML frontmatter, setup instructions, and practical code examples
using the new TablesDB API terminology.
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughAdds Agent Skills generation: a new PHP language class Changes
Sequence Diagram(s)mermaid Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 9
🤖 Fix all issues with AI agents
In `@templates/agent-skills/cli.md.twig`:
- Around line 50-52: The deprecation note incorrectly refers to "class"
terminology; update the wording to reference CLI commands instead. Replace the
sentence that mentions `TablesDB` and `Databases` so it reads something like:
"Use `tablesDB` commands (not the deprecated `databases` commands) for all new
work; only use `databases` if existing CLI scripts rely on it or the user
explicitly requests it." Edit the template line referencing
`TablesDB`/`Databases` accordingly in the `cli.md.twig` content.
- Around line 106-109: Update the outdated runtime value used in the CLI
example: replace the --runtime="node-18.0" flag in the template example with a
current LTS runtime such as --runtime="node-20.0" (or --runtime="node-22.0"),
ensuring the command shown (the {{ spec.title | caseLower }} functions create
... --runtime="...") uses the supported Node.js version.
In `@templates/agent-skills/dart.md.twig`:
- Around line 55-85: Add a Dart "Update row" example to match other language
templates: call TablesDB.updateRow with parameters databaseId, tableId, rowId
(use ID.unique() or placeholder like '[ROW_ID]'), and provide a data map (e.g.,
{'title': 'Updated Title'}); place this new snippet between the listRows
(results) example and the deleteRow block so the sequence is create -> query ->
update -> delete, referencing the updateRow method and TablesDB class shown in
the diff.
In `@templates/agent-skills/deno.md.twig`:
- Around line 22-27: The Deno example uses Client without importing it; add a
URL-based import like the InputFile example to avoid broken code—e.g., add a
top-line import: import { Client, Users, TablesDB, Storage, ID, Query } from
"https://deno.land/x/{{ spec.title | caseLower }}/mod.ts"; then keep the
existing client creation code that calls
Client().setEndpoint(...).setProject(...).setKey(...); ensure the import uses
the same module name pattern as InputFile to match other symbols used in the
template.
In `@templates/agent-skills/flutter.md.twig`:
- Around line 103-104: The call to storage.getFilePreview returns a
Future<Uint8List> but is assigned to preview without awaiting; update the
storage.getFilePreview invocation (the preview variable assignment) to use await
so preview holds the actual bytes rather than a Future, and ensure the enclosing
function is marked async if not already (referencing getFilePreview, preview,
and storage.getFilePreview).
In `@templates/agent-skills/go.md.twig`:
- Around line 44-50: The template uses a hardcoded "[USER_ID]" when calling
service.Create which should instead generate a unique ID like other templates;
update the call in the Go template so the first argument is produced by the ID
generation utility (equivalent to ID.unique()) rather than the literal string,
keeping the rest of the call (email, password, users.WithCreateName) unchanged
so service.Create receives a real unique user ID.
In `@templates/agent-skills/kotlin.md.twig`:
- Around line 22-28: The template is missing an import for InputFile used at
InputFile.fromPath(...); update the import block (the series of io.{{ spec.title
| caseLower }}.* imports) to include the InputFile type so the Kotlin template
compiles—add an import entry for InputFile (the same package where InputFile is
defined in this project/runtime) alongside Client, ID, Query, Users, TablesDB,
and Storage.
In `@templates/agent-skills/php.md.twig`:
- Around line 22-34: The import block for the PHP example is missing the
InputFile class, causing a class-not-found when calling InputFile::withPath(...)
in the example; update the top import list (the same block that contains Client,
ID, Query, Services\Users, Services\TablesDB, Services\Storage) to include use
{{ spec.title }}\InputFile; so the example can call InputFile::withPath(...)
without errors.
In `@templates/agent-skills/web.md.twig`:
- Around line 145-158: The real-time subscription examples use outdated channel
paths; update the two client.subscribe calls in the snippet (the calls to
client.subscribe and the unsubscribe variable) to use the SDK-supported channel
format: replace 'databases.[DATABASE_ID].tables.[TABLE_ID].rows' with
'collections.[COLLECTION_ID].documents' and replace 'buckets.[BUCKET_ID].files'
with 'collections.[BUCKET_ID]' (or the correct collections path used by your SDK
templates), ensuring the unsubscribe variable still references the returned
subscription handle from the first subscribe call.
🧹 Nitpick comments (7)
templates/agent-skills/php.md.twig (2)
67-69: Variable$docis a leftover from the old "document" terminology.Since this PR is specifically migrating to TablesDB with row/table/column naming, consider renaming
$doc→$rowhere (and the correspondingdocvariables in the other language templates) to stay consistent with the new terminology being promoted.
56-84: PHP Database section lacks a "Create table" example.The Dart template (line 62) includes a
createTableexample between database creation and row creation, but this PHP template jumps straight fromcreate(database) tocreateRow. Consider adding acreateTablecall for completeness, or removing it from Dart — the set of demonstrated operations should be consistent across languages.templates/agent-skills/python.md.twig (2)
22-34:InputFileimport is split from the main imports block.The
InputFileimport on line 89 is shown inside the File Storage code block, while all other imports are in the setup section (lines 23–28). Consider consolidating it into the setup imports for consistency, so users see all required imports in one place.Proposed fix
In the setup block (lines 22–34), add the import:
from {{ spec.title | caseLower }}.services.storage import Storage +from {{ spec.title | caseLower }}.input_file import InputFileIn the File Storage block (lines 88–101), remove the redundant import:
```python -from {{ spec.title | caseLower }}.input_file import InputFile - storage = Storage(client)Also applies to: 88-89
40-54: Positional arguments reduce readability for a documentation template.The
users.create()call uses positional args with a mysteriousNone(presumably forphone). In a skill file meant to guide AI agents, keyword arguments would be clearer and less error-prone — consistent with how the other templates (Kotlin, Swift, Dart) use named parameters.-user = users.create(ID.unique(), 'user@example.com', None, 'password123', 'User Name') +user = users.create( + user_id=ID.unique(), + email='user@example.com', + password='password123', + name='User Name' +)templates/agent-skills/go.md.twig (1)
97-99: Go import shown inside a code block mid-file is misleading.In Go, all imports must be declared at the top of a file. Showing
import "...file"inside the File Storage code block (line 98) could mislead users. Consider noting it should be added to the top-level import block, or include it in the setup imports.templates/agent-skills/android.md.twig (1)
22-33: Missing imports for classes used in code examples.The setup imports (lines 23–28) include
Client,ID,Query,Account,TablesDB, andStorage, but the code examples also useRealtime(line 131),InputFile(line 113),File(line 113), andOAuthProvider(line 57) without importing them. For a skill document guiding AI agents, all required imports should be visible.Proposed fix
import io.{{ spec.title | caseLower }}.services.TablesDB import io.{{ spec.title | caseLower }}.services.Storage +import io.{{ spec.title | caseLower }}.services.Realtime +import io.{{ spec.title | caseLower }}.models.InputFile +import io.{{ spec.title | caseLower }}.enums.OAuthProvider +import java.io.Filetemplates/agent-skills/deno.md.twig (1)
92-111:InputFileimport can be consolidated with the main imports.If the main SDK imports are added to the setup section (as suggested above), the standalone
InputFileimport on line 95 becomes redundant and should either be merged into the main import or removed from this section to avoid confusion about where imports belong.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 8
🤖 Fix all issues with AI agents
In @.agents/skills/skill-creator/scripts/init_skill.py:
- Around line 287-288: Validate the skill name read from sys.argv[1] (variable
skill_name) against the documented constraints (kebab-case, lowercase-only, max
64 characters, allowed chars a-z0-9 and hyphen, no leading/trailing hyphen or
consecutive hyphens) before using it in any .format() templates; if invalid,
print the usage/error and exit non-zero. Implement a small validator function
(e.g., is_valid_skill_name(name)) and call it where skill_name is assigned,
rejecting names with spaces, uppercase letters, special characters (including
braces) or length >64 to prevent malformed output when passed into .format()
calls that reference skill_name.
In @.agents/skills/skill-creator/scripts/package_skill.py:
- Line 16: The import of validate_skill from quick_validate is a bare module
import that will fail when the script is executed from outside the scripts/
directory; update package_skill.py to ensure quick_validate.py is discoverable
before importing validate_skill by prepending the script directory to sys.path
(use Path(__file__).resolve().parent and sys.path.insert(0, str(...))) or switch
to a package-relative import if appropriate, then import validate_skill;
reference the symbol validate_skill and the module quick_validate in your change
so the import always succeeds regardless of current working directory.
In @.agents/skills/skill-creator/scripts/quick_validate.py:
- Around line 26-29: The frontmatter extraction in quick_validate.py uses a
regex that only matches Unix line endings (the line with re.match and variable
match); update it to handle Windows CRLF by normalizing content =
content.replace('\r\n','\n') before the regex or change the pattern to use \r?\n
(e.g., r'^---\r?\n(.*?)\r?\n---') so the match variable correctly captures
frontmatter across both Windows and Unix line endings.
- Around line 58-71: The validation currently lets blank/whitespace-only values
pass because the `if name:` guard skips checks; after retrieving `name =
frontmatter.get('name', '')` and stripping it (`name = name.strip()`), add an
explicit required-field check that returns False with a clear message when `name
== ""` (e.g., "Name is required and cannot be empty or whitespace"); then
continue the kebab-case/length checks as before. Apply the same explicit
required/strip-and-check logic to `description` (after `description =
frontmatter.get('description', '')` and `description = description.strip()`),
returning a similar error when empty.
In @.agents/skills/skill-creator/SKILL.md:
- Line 113: Summary: Fix the spelling typo "auxilary" to "auxiliary" in the
SKILL.md content. Locate the string "auxilary" in the skill description (the
sentence mentioning "auxilary context about the process...") and replace it with
the correct spelling "auxiliary"; ensure no other occurrences remain and run a
quick search for "auxilary" to update any other instances in the document.
- Around line 314-315: The statement "Do not include any other fields in YAML
frontmatter" contradicts the file's own frontmatter and the validator; update
the SKILL.md wording to list or permit the actual allowed fields (at minimum
include license, allowed-tools, metadata, compatibility) to match
quick_validate.py and the example frontmatter in this file (which contains
license). Edit the sentence in SKILL.md to explicitly state which fields are
allowed or remove the absolute prohibition so authors aren't misled, and ensure
the text references the validator's allowed-fields behavior rather than a
blanket ban.
- Around line 152-160: Update the example directory tree in SKILL.md to use the
plural directory name `references/` (not `reference/`) so it matches the anatomy
section and other examples; modify the snippet under the `bigquery-skill/`
example (the line showing `reference/`) to `references/` and ensure any listed
child files (e.g., `finance.md`, `sales.md`, `product.md`, `marketing.md`)
remain under `references/`.
In `@templates/agent-skills/kotlin.md.twig`:
- Line 159: Replace the use of InputFile.fromFile(File(...)) with the idiomatic
InputFile.fromPath(...) in the template: locate the call to
InputFile.fromFile(File("/path/to/file.png")) and change it to
InputFile.fromPath("/path/to/file.png") so the template uses the
InputFile.fromPath method from the InputFile class instead of wrapping the path
in a java.io.File.
🧹 Nitpick comments (6)
templates/agent-skills/base/frontmatter.md.twig (1)
1-4: Consider quoting thedescriptionvalue to prevent YAML parsing issues.If
langDescriptioncontains colons, quotes, or other YAML-special characters, the generated frontmatter will be malformed. Wrapping the value in quotes (or using a Twig filter to escape YAML) would make this more robust.--- name: {{ spec.title | caseLower }}-{{ lang }} -description: {{ langDescription }} +description: "{{ langDescription }}" ---.agents/skills/skill-creator/scripts/package_skill.py (1)
67-75: No exclusion filter — common artifacts will be packaged.
skill_path.rglob('*')packages everything, including.git/,__pycache__/,.DS_Store,*.pyc, etc. Consider filtering out common unwanted patterns:Proposed fix
+ EXCLUDE_PATTERNS = {'.git', '__pycache__', '.DS_Store', '*.pyc'} for file_path in skill_path.rglob('*'): - if file_path.is_file(): + if file_path.is_file() and not any( + part.startswith('.git') or part == '__pycache__' + for part in file_path.relative_to(skill_path).parts + ) and file_path.name != '.DS_Store' and file_path.suffix != '.pyc': arcname = file_path.relative_to(skill_path.parent)templates/agent-skills/python.md.twig (2)
37-51: Positional arguments reduce readability of the example code.Line 41 uses
users.create(ID.unique(), 'user@example.com', None, 'password123', 'User Name')with a bareNonefor the phone parameter. In SDK documentation meant to teach usage, keyword arguments would be clearer and more Pythonic:user = users.create( user_id=ID.unique(), email='user@example.com', password='password123', name='User Name' )This also avoids the unexplained
Nonewhich could confuse readers.
86-101:InputFileimport placed mid-file rather than at the top.The
InputFileimport on line 89 is separated from the other imports (lines 17–23). While this works, it's unconventional for Python and could teach bad habits. Consider moving it to the main import block at the top..agents/skills/skill-creator/references/output-patterns.md (1)
64-68: Inner fenced code blocks lack language identifiers (markdownlint MD040).The commit message examples at lines 64 and 73 use bare
```fences. Adding a language hint (e.g.,```text) would satisfy the linter and improve rendering in some Markdown processors.Also applies to: 73-77
.agents/skills/skill-creator/scripts/init_skill.py (1)
236-261: Partial state left on failure—no cleanup of the skill directory.If file creation fails partway through (e.g.,
SKILL.mdis written butscripts/example.pyfails), the function returnsNonebut leaves the partially created directory behind. For a scaffolding tool this is tolerable, but a cleanup step would make it more robust.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In `@templates/agent-skills/go.md.twig`:
- Around line 66-72: The snippet calling service.CreateRow uses a hardcoded
"[ROW_ID]" placeholder; replace this with a generated unique ID before the
CreateRow call (e.g., create a rowID variable using a UUID generator or existing
generateID helper) and pass that rowID into CreateRow so each new row gets a
unique identifier; update imports if needed and reference CreateRow and the
placeholder "[ROW_ID]" when making the change.
- Around line 16-28: The setup block is missing the "os" import and the SDK's id
package; update the import list to include "os" and the id package (e.g.,
"github.com/{{ sdk.gitUserName }}/sdk-for-go/id") so os.Getenv calls in the
client.New block work and unique ID generation is available for use; ensure any
places that call id generation (e.g., id.Generate or similar) reference the
imported id package.
🧹 Nitpick comments (1)
templates/agent-skills/swift.md.twig (1)
34-35: Force-unwrapping environment variables will crash if unset.Using
!onProcessInfo.processInfo.environment[...]will cause a runtime crash if the env var is missing. Consider usingguard letor a nil-coalescing fallback in the example to model safer patterns.Proposed fix
- .setProject(ProcessInfo.processInfo.environment["{{ spec.title | caseUpper }}_PROJECT_ID"]!) - .setKey(ProcessInfo.processInfo.environment["{{ spec.title | caseUpper }}_API_KEY"]!) + .setProject(ProcessInfo.processInfo.environment["{{ spec.title | caseUpper }}_PROJECT_ID"] ?? "") + .setKey(ProcessInfo.processInfo.environment["{{ spec.title | caseUpper }}_API_KEY"] ?? "")
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🤖 Fix all issues with AI agents
In `@templates/agent-skills/go.md.twig`:
- Around line 60-72: Replace hardcoded placeholder IDs with unique ID generation
in the Go template: import and use the equivalent of an ID.unique() helper and
call it for database, row and file creation so that service.Create,
service.CreateRow and service.CreateFile receive generated IDs instead of
"[DATABASE_ID]", "[ROW_ID]" and "[FILE_ID]"; ensure you add the id import and
replace the literal strings on the Create (previously at service.Create),
CreateRow, and CreateFile calls so examples consistently demonstrate unique ID
generation.
- Around line 262-274: The CreateRow example uses a literal "[ROW_ID]"
placeholder instead of generating a unique ID; update the call to
service.CreateRow to pass id.Unique() for the row id (keep the rest of the
permissions block as-is) so the example matches the main Database section;
locate the usage in the CreateRow invocation in this template
(service.CreateRow) and replace the "[ROW_ID]" placeholder with id.Unique().
In `@templates/agent-skills/python.md.twig`:
- Around line 182-191: The template uses OAuthProvider.Github in the oauth()
example but never imports OAuthProvider; add an import for OAuthProvider (from
wherever it is exported in your codebase) to the module-level setup/import block
or, alternatively, import OAuthProvider inside the oauth() function before
calling Account.create_o_auth2_token so the name is defined when oauth() runs;
ensure you reference the same OAuthProvider symbol used in the example and keep
the Account and create_o_auth2_token calls unchanged.
🧹 Nitpick comments (1)
templates/agent-skills/python.md.twig (1)
37-51: PositionalNoneargument inusers.createmay be fragile.Line 41 passes
Noneas the third positional argument (presumably the phone parameter). This is valid Python, but for a skill file meant to guide AI agents, using the keyword argument explicitly would reduce ambiguity and be more resilient to SDK signature changes.
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@templates/agent-skills/kotlin.md.twig`:
- Around line 22-34: The client import block is missing imports for
OAuthProvider and Realtime which are referenced later; update the Kotlin
client-side import section to add imports for OAuthProvider and Realtime (so
symbols OAuthProvider.GOOGLE and Realtime(client) resolve), placing them
alongside the existing imports (e.g., next to Account, Storage, TablesDB) to
ensure the generated Kotlin code compiles.
🧹 Nitpick comments (2)
templates/agent-skills/kotlin.md.twig (1)
277-306: Force-unwrap (!!) on query parameters risksNullPointerException.Lines 295–296 use
call.parameters["userId"]!!andcall.parameters["secret"]!!. If the OAuth callback is hit without these parameters (e.g., user navigates directly or provider error), this will throw an unhandled NPE. Since this is a skill file consumed by AI agents that may reproduce the pattern verbatim, consider safe handling.Suggested safer pattern
- val session = account.createSession( - userId = call.parameters["userId"]!!, - secret = call.parameters["secret"]!!, - ) + val userId = call.parameters["userId"] + ?: return@get call.respond(HttpStatusCode.BadRequest) + val secret = call.parameters["secret"] + ?: return@get call.respond(HttpStatusCode.BadRequest) + val session = account.createSession(userId = userId, secret = secret)templates/agent-skills/python.md.twig (1)
36-52: Consider using keyword arguments forusers.create()to improve clarity.Line 42 uses positional arguments with a
Noneplaceholder for the phone parameter:users.create(ID.unique(), 'user@example.com', None, 'password123', 'User Name'). Since this is a skill file consumed by AI agents, explicit keyword arguments would make the parameter semantics unambiguous and less error-prone when the SDK signature changes.Suggested improvement
-user = users.create(ID.unique(), 'user@example.com', None, 'password123', 'User Name') +user = users.create( + user_id=ID.unique(), + email='user@example.com', + password='password123', + name='User Name' +)
Summary
AgentSkillslanguage class that generates 16 markdown skill files — one per supported SDK language (web, node, react-native, deno, flutter, dart, android, apple, kotlin, swift, php, python, ruby, go, dotnet, cli){lang}/SKILL.mdwith YAML frontmatter, client setup, and practical code examples following each language's naming conventionsTablesDBAPI (tables/rows/columns) with a deprecation note for the oldDatabasesclassexample.php— run withphp example.php agent-skillsTest plan
php example.php agent-skillsand verify 16 folders are generated underexamples/agent-skills/SKILL.mdhas valid YAML frontmatterTablesDBwith table/row/column terminology{{ spec.title }}Summary by CodeRabbit
New Features
Documentation