Edgeone Makers Tools
TencentEdgeOne/edgeone-makers-tools
EdgeOne Makers platform development router — the single entry point for building, storing data, and deploying on Tencent EdgeOne Makers.
Step-by-step guide for adding a new agent framework adapter to Agent Kernel.
$ npx skills add yaalalabs/agent-kernel --skill ak-dev-new-framework-integration -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install yaalalabs/agent-kernel ak-dev-new-framework-integration --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/yaalalabs/agent-kernel.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.agents/skills/ak-dev-new-framework-integration .claude/skills/ak-dev-new-framework-integration && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "ak-dev-new-framework-integration" agent skill from https://github.com/yaalalabs/agent-kernel/tree/develop/.agents/skills/ak-dev-new-framework-integration into .claude/skills/ak-dev-new-framework-integration/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ak-dev-new-framework-integration", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/yaalalabs/agent-kernel/tree/develop/.agents/skills/ak-dev-new-framework-integrationType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add yaalalabs/agent-kernel --skill ak-dev-new-framework-integration -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install yaalalabs/agent-kernel ak-dev-new-framework-integration --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/yaalalabs/agent-kernel.git skills-src && mkdir -p .agents/skills && cp -r skills-src/.agents/skills/ak-dev-new-framework-integration .agents/skills/ak-dev-new-framework-integration && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "ak-dev-new-framework-integration" agent skill from https://github.com/yaalalabs/agent-kernel/tree/develop/.agents/skills/ak-dev-new-framework-integration into .agents/skills/ak-dev-new-framework-integration/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ak-dev-new-framework-integration", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add yaalalabs/agent-kernel --skill ak-dev-new-framework-integration -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install yaalalabs/agent-kernel ak-dev-new-framework-integration --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/yaalalabs/agent-kernel.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/.agents/skills/ak-dev-new-framework-integration .cursor/skills/ak-dev-new-framework-integration && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "ak-dev-new-framework-integration" agent skill from https://github.com/yaalalabs/agent-kernel/tree/develop/.agents/skills/ak-dev-new-framework-integration into .cursor/skills/ak-dev-new-framework-integration/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ak-dev-new-framework-integration", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/yaalalabs/agent-kernel.git --path .agents/skills/ak-dev-new-framework-integration--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add yaalalabs/agent-kernel --skill ak-dev-new-framework-integration -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install yaalalabs/agent-kernel ak-dev-new-framework-integration --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/yaalalabs/agent-kernel.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/.agents/skills/ak-dev-new-framework-integration .gemini/skills/ak-dev-new-framework-integration && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "ak-dev-new-framework-integration" agent skill from https://github.com/yaalalabs/agent-kernel/tree/develop/.agents/skills/ak-dev-new-framework-integration into .gemini/skills/ak-dev-new-framework-integration/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ak-dev-new-framework-integration", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install yaalalabs/agent-kernel ak-dev-new-framework-integrationInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add yaalalabs/agent-kernel --skill ak-dev-new-framework-integration -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/yaalalabs/agent-kernel.git skills-src && mkdir -p .github/skills && cp -r skills-src/.agents/skills/ak-dev-new-framework-integration .github/skills/ak-dev-new-framework-integration && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "ak-dev-new-framework-integration" agent skill from https://github.com/yaalalabs/agent-kernel/tree/develop/.agents/skills/ak-dev-new-framework-integration into .github/skills/ak-dev-new-framework-integration/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ak-dev-new-framework-integration", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add yaalalabs/agent-kernel --skill ak-dev-new-framework-integration -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install yaalalabs/agent-kernel ak-dev-new-framework-integration --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/yaalalabs/agent-kernel.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/.agents/skills/ak-dev-new-framework-integration .opencode/skills/ak-dev-new-framework-integration && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "ak-dev-new-framework-integration" agent skill from https://github.com/yaalalabs/agent-kernel/tree/develop/.agents/skills/ak-dev-new-framework-integration into .opencode/skills/ak-dev-new-framework-integration/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ak-dev-new-framework-integration", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
ak-dev-new-framework-integrationStep-by-step guide for adding a new agent framework adapter to Agent Kernel.
Ak Dev New Framework Integration is an agent skill from yaalalabs/agent-kernel. Step-by-step guide for adding a new agent framework adapter to Agent Kernel. Use this skill when you need to integrate a new agent framework (beyond OpenAI, CrewAI, LangGraph, Google ADK, Smolagents, Pydantic AI). Covers creating the adapter module, implementing Agent/Runner/Module subclasses, adding optional dependencies, exports, and tests.
Its SKILL.md is about 5.7k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.
It sits in AI & LLM Engineering, covering Building AI agents. It works with OpenAI, LangGraph, CrewAI and Pydantic AI. The repository describes itself as: The Operating System for Scalable Enterprise AI Agents - Run, orchestrate, and deploy Compliant Enterprise AI Agents at scale across frameworks, without lock-in, rewrites or… The licence is Apache-2.0.
12 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit e03a602. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
No scripts in the folder and no shell commands in SKILL.md (its code samples are python and toml).
From the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Ak Dev New Framework Integration loads about 5.7k tokens when it runs. Until then it costs about 95 tokens; SKILL.md has 1,752 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from yaalalabs/agent-kernel at commit e03a602, republished under its Apache-2.0 licence (© yaalalabs). 1,752 words, ~5,682 tokens.
.claude/skills/ak-dev-new-framework-integration/SKILL.md (or your agent's skills folder).This guide walks through adding support for a new agent framework to Agent Kernel. Use the existing OpenAI adapter (ak-py/src/agentkernel/framework/openai/) as the canonical reference implementation.
.agents/skills/ak-dev-architecture/SKILL.md)ak-py/src/agentkernel/framework/<name>/
├── __init__.py
└── <name>.pyReplace <name> with the framework's lowercase identifier (e.g., openai, langgraph).
If the framework requires per-session state (e.g., conversation history), create a session data class:
class <Name>Session:
"""Stores framework-specific session data."""
def __init__(self):
self._history = [] # or whatever state the framework needs
def get_history(self):
return self._history
def add_to_history(self, item):
self._history.append(item)
def clear_session(self):
self._history.clear()The session data is stored in the Agent Kernel Session via session.set("<name>", <Name>Session()) and retrieved via session.get("<name>"). This key must be the same string passed as your Runner's name (see Step 3) — hook authors reach it via Session.get_framework_session(), which resolves Agent.current().runner.name under the hood.
Subclass Runner from agentkernel.core.base:
from agentkernel.core.base import Runner, Session
from agentkernel.core.model import AgentReply, AgentReplyText, AgentRequest, AgentRequestText
from agentkernel.core.tool import ToolContext
FRAMEWORK = "<name>"
class <Name>Runner(Runner):
def __init__(self):
# must match the session key below — Session.get_framework_session() resolves it
# via Agent.current().runner.name
super().__init__(FRAMEWORK)
def _session(self, session: Session) -> <Name>Session:
"""Get or create framework-specific session data."""
data = session.get(FRAMEWORK)
if data is None:
data = <Name>Session()
session.set(FRAMEWORK, data)
return data
async def run(self, agent, session: Session, requests: list[AgentRequest]) -> AgentReply:
# 1. Create ToolContext for tool functions to access
tool_context = ToolContext(
runtime=Runtime.current(),
agent=agent,
session=session,
requests=requests
)
with tool_context:
tool_context.set()
try:
# 2. Get framework-specific session state
fw_session = self._session(session)
# 3. Convert AgentRequest models to framework-native format
# e.g., extract text from AgentRequestText
prompt = ""
for req in requests:
if isinstance(req, AgentRequestText):
prompt = req.prompt
# 4. Call the framework's execution API
result = await self._execute(agent, fw_session, prompt) # framework-specific
# 5. Update session state
fw_session.add_to_history({"input": prompt, "output": result})
# 6. Return as AgentReply
return AgentReplyText(response=str(result), prompt=prompt)
finally:
tool_context.reset()Key requirements:
ToolContext and set it so tool functions can access ToolContext.get()ToolContext in a finally blockAgentRequest subtypes (AgentRequestText, AgentRequestImage, AgentRequestFile)AgentReply (AgentReplyText or AgentReplyImage)run() and once per stream() with options = await agent.resolve_run_options(session, requests) (#758), after the request-shape early returns and before the framework-context load, then build the native call's keyword arguments with self._native_kwargs(options, <ak_owned>=...) (#754), never a fixed keyword set: the resolved per-agent run options (the static declaration with a per-run factory's result merged over it) are copied first and the keys your adapter populates (the session, the framework context, the input) are written last. Pass the same mapping to any helper of yours that reads options; never read agent.run_options at a call site. If the framework's options object and yours are one object (LangGraph's config) or must be adjusted per mode (ADK's RunConfig in stream mode), merge or copy it before passing it as an AK-owned key, and do the same in stream()stream() with AK Stream EventsRunner declares stream() as @abstractmethod, returning AsyncGenerator[StreamEvent, None] —
every adapter must implement it, even if the framework doesn't support token streaming, and it
must yield StreamEvent members (core/event.py: MessageStart/TextDelta/MessageEnd,
ReasoningStart/ReasoningDelta/ReasoningEnd, ToolCallStart/ToolCallArgs/ToolCallEnd/
ToolCallResult, StepStart/StepEnd) — never a bare str. A runner that yields a bare str is
rejected by StreamChunk.event with a pydantic.ValidationError; there is no string-normalisation
fallback in Runtime.stream().
If the framework's SDK exposes a token-delta stream, map its native events onto AK events —
bracket assistant text with MessageStart/MessageEnd (deferred until text actually arrives, so a
tool-only turn doesn't emit an empty message), and map tool-call/tool-result events onto
ToolCallStart/ToolCallArgs/ToolCallEnd/ToolCallResult correlated by the framework's own call
id where one exists (never generate an id when the framework supplies one — a generated id cannot
correlate a result to the call that produced it):
from collections.abc import AsyncGenerator
from ...core.event import MessageEnd, MessageStart, StreamEvent, TextDelta
async def stream(self, agent, session: Session, requests: list[AgentRequest]) -> AsyncGenerator[StreamEvent, None]:
tool_context = ToolContext(Runtime.current(), agent, session, requests)
try:
tool_context.set()
fw_session = self._session(session)
prompt = "".join(req.prompt for req in requests if isinstance(req, AgentRequestText))
# Anything remembered mid-stream is a local — see the rule below.
message_id: str | None = None
result = await self._execute_streamed(agent, fw_session, prompt) # framework-specific
message_id: str | None = None # local — the runner is shared across sessions
async for event in result:
delta = self._extract_text_delta(event) # framework-specific
if delta:
if message_id is None:
message_id = uuid4().hex
yield MessageStart(message_id=message_id)
yield TextDelta(message_id=message_id, content=delta)
if message_id is not None:
yield MessageEnd(message_id=message_id)
finally:
tool_context.reset()If the framework has no native token streaming (e.g. CrewAI, smolagents), override supports_streaming to False and implement stream() as a generator that always raises, so a caller can check the property before invoking stream() instead of provoking the raise, while stream() itself still satisfies the abstract method contract and fails fast with a clear message:
async def stream(self, agent: Any, session: Session, requests: list[AgentRequest]) -> AsyncGenerator[StreamEvent, None]:
"""
:return: False — this adapter does not implement streaming, so stream() always raises.
"""
return False
async def stream(self, agent: Any, session: Session, requests: list[AgentRequest]) -> AsyncGenerator[StreamEvent, None]:
"""
<Name> streaming is not implemented in this adapter yet.
:raises NotImplementedError: Always raised — use rest_sync mode instead.
"""
raise NotImplementedError(
"<Name> streaming is not implemented in the Agent Kernel adapter yet. Use rest_sync mode."
)
yield # make this an async generator to satisfy the type contract
@property
def supports_streaming(self) -> bool:
"""Declared False so a caller can reject a streamed request instead of provoking the raise."""
return FalseRuntime.stream() runs every yielded event through PostHook.on_stream_event() (#670), wraps what
survives in a StreamChunk (delta is populated only for TextDelta, so a plain-text consumer that
only reads StreamChunk.delta keeps working unchanged), and forwards it to the caller (REST SSE
endpoint or AWS Lambda WebSocket/SQS pipeline). No other core changes are needed to support a new
framework's streaming — just implement Runner.stream(). See docs/specs/523-ag-ui-support/spec.md
for the full event-mapping rules and per-adapter correlation-id/boundary-derivation decisions, and
docs/specs/670-streaming-post-hooks/ for the hook contract your events pass through.
Two consequences for a new adapter, both from #670: a hook may now drop or rewrite any event you
emit, including boundaries, so do not assume what you yield is what the client receives; and a hook
raising StreamHalt abandons your generator mid-iteration, so anything your stream() does after the
loop (writing back framework context, for instance) will not run on a halted run.
The base Runner provides two helpers so a caller-supplied, framework-agnostic context/state dict
(seeded by a hook via session.set_framework_context(...)) rides across turns. Your run() and
stream() must call them and map the one AK-level dict onto your framework's native
context/state mechanism (or decline it explicitly, as CrewAI does):
incoming = self._load_framework_context(session) — call before the native invocation.
Returns a deep copy of the stored dict, or None when the key is absent. When None, inject
nothing (framework default) — this keeps the no-context path unchanged for existing apps.incoming (when not None) via the framework's native mechanism (a run context=, an
input state channel, a session-state delta, additional_args=, …).produced and call
self._store_framework_context(session, incoming, produced). This shallow-merges produced over
incoming (framework-touched top-level keys win; untouched caller keys preserved) and fail-fast
checks picklability before writing back.# In run(), inside the existing try, around the native call:
incoming = self._load_framework_context(session)
result = await self._execute(agent, fw_session, prompt, context=incoming) # inject natively
produced = self._extract_state(result, incoming) # framework-specific; may be a subset of keys
self._store_framework_context(session, incoming, produced) # only after a successful callPlacement matters (atomicity): put the write-back inside the try, after the native call,
before the except — and for stream(), after the async for loop but still inside the
try, never in finally. A framework error or a client disconnect (GeneratorExit) then unwinds
before it, leaving the previously stored context intact rather than persisting partial state.
Seed AK-internal keys last. If you inject the caller's dict by merging it into a native state
dict that also carries AK-internal entries, assign the internal ones after the caller's keys so a
caller key can never displace them (ak_tool_context in ADK, messages in LangGraph). The failures
this prevents are silent and confusing — a broken tool-context lookup, or a replaced message list.
Watch for injection side effects. A framework's "context" slot is not always private: smolagents'
additional_args is merged into the agent state and appended to the task prompt, so the caller's
dict reaches the model. If your framework does something similar, document it on the framework's page
so callers know not to put secrets in framework_context.
Declare your round-trip fidelity honestly in the framework's docs and the fidelity table in
docs/docs/core-concepts/runner.md — how much of a caller dict actually survives depends on the
framework (full round-trip, filtered to seeded keys, declared-channels-only, or unsupported). Name the
native handle a tool uses to reach the context (RunContextWrapper.context on OpenAI,
RunContext.deps on Pydantic AI, tool_context.state on ADK, …) — tools use that, never the Session
accessors. If the framework has no safe caller-state slot, do not inject; instead log a single
warning per runner instance and skip both load and write-back (see the CrewAI adapter for the pattern).
Subclass Agent from agentkernel.core.base:
from agentkernel.core.base import Agent, Runner, Session
class <Name>Agent(Agent):
def __init__(self, name: str, runner: Runner, native_agent):
super().__init__(name, runner)
self._native_agent = native_agent
def get_description(self) -> str:
# Return the agent's description from the native framework object
return self._native_agent.instructions # framework-specific
def get_a2a_card(self):
from agentkernel.core.builder import A2ACardBuilder
return A2ACardBuilder.build(
name=self.name,
description=self.get_description(),
skills=[...] # extract from agent tools
)Key requirements:
get_description() must return a meaningful description from the native framework agentget_a2a_card() must return a valid A2A agent card built via A2ACardBuilderself._native_agent for access in the RunnerRESERVED_RUN_OPTIONS: ClassVar[Mapping[str, str]] (#754): every keyword your runner passes itself, plus any that changes the result shape your reply mapping reads, each mapped to a one-line reason. Module.run_options rejects them at declaration with that reason. Override validate_run_options only for a nested key (LangGraph's config.configurable.thread_id)Subclass ToolBuilder from agentkernel.core.tool:
from agentkernel.core.tool import ToolBuilder
class <Name>ToolBuilder(ToolBuilder):
@classmethod
def bind(cls, funcs: list) -> list:
"""Wrap plain Python functions into framework-native tool objects."""
tools = []
for func in funcs:
# Convert func to framework-specific tool format
tool = framework_specific_tool_wrapper(func)
tools.append(tool)
return toolsSubclass Module from agentkernel.core.module:
from agentkernel.core.module import Module
from agentkernel.trace.trace import Trace
class <Name>Module(Module):
def __init__(self, agents: list):
super().__init__()
# Check if tracing is enabled, use traced runner if so
trace_runner = Trace.get().<name>() # returns Runner or None
self.runner = trace_runner if trace_runner else <Name>Runner()
self.load(agents)
def _wrap(self, agent, agents) -> <Name>Agent:
return <Name>Agent(agent.name, self.runner, agent)
def load(self, agents: list) -> "Module":
return super().load(agents)
# pre_hook / post_hook / run_options are inherited from Module: they resolve the wrapped agent
# through _native_agent_name(agent), which defaults to agent.name. Override that hook only when
# your framework registers agents under something else (CrewAI: role).Key requirements:
self.load(agents)_wrap() creates the Agent wrapper — the agent name must come from the native agentTrace.get().<name>()pre_hook, post_hook and run_options are inherited and concrete (they share Module._wrapped, which raises ValueError for an agent not loaded in the module); override _native_agent_name(agent) only when the native agent is not registered under agent.name (CrewAI uses role, smolagents a fallback name)__init__.py# ak-py/src/agentkernel/framework/<name>/__init__.py
from .<name> import <Name>Module, <Name>ToolBuilderCreate ak-py/src/agentkernel/<name>.py:
from .framework.<name> import <Name>Module, <Name>ToolBuilderThis allows users to import as from agentkernel.<name> import <Name>Module.
Add the framework to ak-py/src/agentkernel/__init__.py if appropriate (following the existing pattern).
In ak-py/pyproject.toml, add an optional dependency group:
[project.optional-dependencies]
<name> = [
"framework-package>=x.y.z",
# Add any instrumentation packages for tracing support
]There are two tracing backends, each with per-framework traced runners. A new framework needs a traced runner under both ak-py/src/agentkernel/trace/langfuse/<name>.py and ak-py/src/agentkernel/trace/openllmetry/<name>.py:
from ...framework.<name>.<name> import <Name>Runner
class LangFuse<Name>Runner(<Name>Runner):
def __init__(self, langfuse_client):
super().__init__()
self._client = langfuse_client
async def run(self, agent, session, requests):
with self._client.start_as_current_span(name=agent.name):
return await super().run(agent, session, requests)Also add a new abstract framework method in ak-py/src/agentkernel/trace/base.py and the corresponding Trace.<name>() method in ak-py/src/agentkernel/trace/trace.py.
Create tests in ak-py/tests/:
# ak-py/tests/test_<name>_runner.py
# ak-py/tests/test_tool_<name>.pyFollow the existing test patterns (e.g. test_openai_runner.py, test_smolagents_runner.py, test_pydanticai_runner.py, test_tool_adk.py) — use DummyRunner, DummyAgent for unit tests, monkeypatch for config overrides, @pytest.mark.asyncio for async tests.
Create at minimum:
examples/cli/<name>/ — CLI demo with demo.py, pyproject.toml, demo_test.pyexamples/api/<name>/ — API demo (optional but recommended)docs/docs/frameworks/<name>.md — note the page slug may differ from the adapter directory name (e.g. the adk adapter's page is docs/docs/frameworks/google-adk.md, referenced as 'frameworks/google-adk' in docs/sidebars.js)docs/sidebars.js to include the new frameworkdocs/src/components/*/data.tsx): add a tile to the Agent frameworks & dev tools row in IntegrationsMarquee/data.tsx (role Framework, href to the new page, logo or react-icons/si glyph); add pick("<tile name>") to the Agent frameworks card in ArchitectureOverview/data.tsx; add the framework to the Framework Adapters card's tags and description under the Build tab in FeatureExplorer/data.tsx. Logo sourcing and the build check are in ak-dev-sync-docs-from-branch, Docs-Site Landing and Features Pagesdocs/src/pages/features.tsx): the integrations list and the "Framework adapters for N SDKs" highlight on the Six Core Abstractions card. Grep docs/src/pages/*.tsx and docs/docs/intro.md for the framework roll call and add the new name wherever the others are listedak-py/src/agentkernel/framework/<name>/ directory with __init__.py and <name>.py<Name>Session (if needed), <Name>Runner, <Name>Agent, <Name>Module, <Name>ToolBuilder<Name>Runner.stream() implemented — either real event streaming or a NotImplementedError stub<Name>Runner.supports_streaming declared — False when stream() only raises, so callers reject instead of provoking it<Name>Runner's name (passed to super().__init__()) matches the session key used in session.get/set(...) — required for Session.get_framework_session() to resolve itak-py/src/agentkernel/<name>.pyak-py/pyproject.tomlak-py/src/agentkernel/trace/langfuse/<name>.py and ak-py/src/agentkernel/trace/openllmetry/<name>.py (optional)trace/base.py and trace/trace.py (if adding tracing)<Name>Agent.RESERVED_RUN_OPTIONS declared; run() and stream() each resolve once with await agent.resolve_run_options(session, requests) after the early returns and pass the mapping to _native_kwargs and your helpers (#754, #758)_native_agent_name overridden if the registered name is not agent.nameak-py/tests/, including: declared run options reach the native call, an AK-owned key wins over a bypassed declaration, the declared dict is not mutated across runs, and the reserved keys are rejected through the module; a factory-merged mapping (a mock whose resolve_run_options returns it) wins over the static key at the native call, and resolve_run_options is awaited exactly once per run and per stream (#758)examples/cli/<name>/docs/docs/frameworks/<name>.mdIntegrationsMarquee/data.tsx), pick() chip on the Agent frameworks card (ArchitectureOverview/data.tsx), Framework Adapters card tags (FeatureExplorer/data.tsx)docs/src/pages/features.tsx (integrations and SDK count) and in docs/docs/intro.md© yaalalabs, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in .agents/skills/ak-dev-new-framework-integration of yaalalabs/agent-kernel.
Open the folder on GitHubat commit e03a602
Ak Dev New Framework Integration next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Ak Dev New Framework Integration this skillyaalalabs/agent-kernel | 191 | — | ~5.7k | Automated safety check: Pass | Apache-2.0 | |
| Edgeone Makers ToolsTencentEdgeOne/edgeone-makers-tools | 1.9k | 1 repos | ~646 | Automated safety check: Pass | MIT | |
| Edgeone Makers ToolsTencentEdgeOne/edgeone-makers-tools | 1.9k | — | ~395 | Automated safety check: Pass | MIT | |
| Agentsop Prompt History Inspectagentsope/SkillAlchemy | 459 | — | ~8.4k | Automated safety check: Pass | MIT | |
| Agentsop LLM Tool Idempotencyagentsope/SkillAlchemy | 459 | — | ~8.4k | Automated safety check: Pass | MIT | |
| Mem0 Platform SDKmem0ai/mem0 | 67k | 2 repos | ~2.2k | Automated safety check: Pass | Apache-2.0 |
TencentEdgeOne/edgeone-makers-tools
EdgeOne Makers platform development router — the single entry point for building, storing data, and deploying on Tencent EdgeOne Makers.
TencentEdgeOne/edgeone-makers-tools
EdgeOne Makers 全栈开发技能包 —— 涵盖 AI Agent 开发(DeepAgents、LangGraph、 Claude SDK、OpenAI Agents、CrewAI)、云函数(Node.js/Go/Python)、边缘函数、 KV 存储、中间件及快速部署,帮助 AI 编程助手准确高效地在 EdgeOne 平台上构建和发布应用。
agentsope/SkillAlchemy
Tool skill — the first move in any LM-debugging session: dump the actual rendered prompt the framework sent to the model, before changing anything else.
agentsope/SkillAlchemy
Decision protocol for making side-effectful agent tools idempotent — so when an LLM tool call is retried (timeout, framework resume, user re-run, model duplicate emit), the second call is a no-op…
mem0ai/mem0
Adds persistent memory to AI apps with the Mem0 Python and TypeScript SDKs: store, search, update and delete user memories, with framework integrations.
GetBindu/Bindu
Add a new self-contained example agent under examples/. An agent skill from GetBindu/Bindu.
yaalalabs/agent-kernel
Code quality standards, formatting, Python style rules (classes over script-style functions, configuration-field rules), commit conventions, and PR workflow for Agent Kernel development.
yaalalabs/agent-kernel
Step-by-step guide for adding a new built-in test evaluator provider to Agent Kernel (beyond DeepEval, Opik and JEV).
yaalalabs/agent-kernel
Step-by-step guide for adding a new guardrail provider to Agent Kernel.
yaalalabs/agent-kernel
Step-by-step guide for adding a new knowledge base backend to Agent Kernel.
yaalalabs/agent-kernel
Step-by-step guide for adding a new messaging platform integration to Agent Kernel.
yaalalabs/agent-kernel
Step-by-step guide for adding a new multimodal attachment storage backend to Agent Kernel.
Works with
Categories
Step-by-step guide for adding a new agent framework adapter to Agent Kernel. Ak Dev New Framework Integration is an agent skill from yaalalabs/agent-kernel. Step-by-step guide for adding a new agent framework adapter to Agent Kernel.
Ak Dev New Framework Integration fits situations like: you need to integrate a new agent framework (beyond OpenAI; tasks that involve Building AI agents.
Run `npx skills add yaalalabs/agent-kernel --skill ak-dev-new-framework-integration -a claude-code`. Or copy the skill folder (.agents/skills/ak-dev-new-framework-integration in yaalalabs/agent-kernel) into .claude/skills/ak-dev-new-framework-integration in your project. Claude Code loads it when a task matches its description.
Run `npx skills add yaalalabs/agent-kernel --skill ak-dev-new-framework-integration -a codex`. Or copy the skill folder (.agents/skills/ak-dev-new-framework-integration in yaalalabs/agent-kernel) into .agents/skills/ak-dev-new-framework-integration in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add yaalalabs/agent-kernel --skill ak-dev-new-framework-integration -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/ak-dev-new-framework-integration, .gemini/skills/ak-dev-new-framework-integration, .github/skills/ak-dev-new-framework-integration and .opencode/skills/ak-dev-new-framework-integration in your project.
SKILL.md names no scripts, command-line tools or credentials: Ak Dev New Framework Integration is instructions for the agent only. Our summary lists: Python 3.
SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Ak Dev New Framework Integration is published under the Apache-2.0 licence (declared in SKILL.md). It allows redistribution, so the full SKILL.md is shown on this page.
About 5.7k tokens (SKILL.md is roughly 23k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Ak Dev New Framework Integration: Edgeone Makers Tools (TencentEdgeOne/edgeone-makers-tools, 1.9k stars), Edgeone Makers Tools (TencentEdgeOne/edgeone-makers-tools, 1.9k stars), Agentsop Prompt History Inspect (agentsope/SkillAlchemy, 459 stars) and Agentsop LLM Tool Idempotency (agentsope/SkillAlchemy, 459 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
yaalalabs (a GitHub organization) maintains it in yaalalabs/agent-kernel, which has 191 GitHub stars. The repository holds 23 skills in this directory. The repository was last updated on October 8, 2026.
Source: yaalalabs/agent-kernel on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.