Skip to content

Commit 83bc993

Browse files
committed
docs: update skill download
1 parent 1a5040e commit 83bc993

17 files changed

Lines changed: 1034 additions & 382 deletions

File tree

docs/docs.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,10 @@
8787
"group": "Long-term Skill",
8888
"icon": "brain",
8989
"pages": [
90-
"learn/skill-memory",
90+
"learn/quick",
9191
{
9292
"group": "Features",
9393
"pages": [
94-
"learn/quick",
9594
"learn/custom-memory",
9695
"learn/learning-spaces"
9796
]

docs/index.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ Session-scoped storage for messages, files, artifacts, and sandboxes — with co
1818
Task status, progress tracking, and automatic summaries.
1919
</Card>
2020

21-
<Card title="Long-term Skill" icon="brain" href="/learn/skill-memory">
21+
<Card title="Long-term Skill" icon="brain" href="/learn/quick">
2222
Persistent skills learned across sessions — filesystem-compatible, configurable, and human-readable.
2323
</Card>
2424

docs/integrations/claude-agent.mdx

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,49 @@ const storage = new ClaudeAgentStorage({
244244
| **ResultMessage** | No | Fallback session-id source. |
245245
| **StreamEvent** | No | Fallback session-id source. |
246246

247+
## Learn and Download Skills
248+
249+
Acontext can automatically learn [long-term skills](/learn/quick) from the stored messages — extracting patterns, user preferences, and domain knowledge into structured markdown files. You can then download these skills to your local filesystem:
250+
251+
<Tabs>
252+
<Tab title="Python">
253+
```python
254+
# Create a learning space and learn from the session
255+
space = await acontext_client.learning_spaces.create()
256+
await acontext_client.learning_spaces.learn(space.id, session_id=storage.session_id)
257+
# your agent runs as usual...
258+
# ...
259+
260+
261+
# Download learned skills to local
262+
skills = await acontext_client.learning_spaces.list_skills(space.id)
263+
for skill in skills:
264+
result = await acontext_client.skills.download(skill_id=skill.id, path=f"./skills/{skill.name}")
265+
print(f"Downloaded {result.name} to {result.dir_path}")
266+
print(f"Files: {result.files}")
267+
```
268+
</Tab>
269+
270+
<Tab title="TypeScript">
271+
```typescript
272+
// Create a learning space and learn from the session
273+
const space = await client.learningSpaces.create();
274+
await client.learningSpaces.learn({ spaceId: space.id, sessionId: storage.sessionId });
275+
276+
// your agent runs as usual...
277+
// ...
278+
279+
// Download learned skills to local
280+
const skills = await client.learningSpaces.listSkills(space.id);
281+
for (const skill of skills) {
282+
const result = await client.skills.download(skill.id, { path: `./skills/${skill.name}` });
283+
console.log(`Downloaded ${result.name} to ${result.dirPath}`);
284+
console.log(`Files: ${result.files}`);
285+
}
286+
```
287+
</Tab>
288+
</Tabs>
289+
247290
## Next Steps
248291

249292
<CardGroup cols={2}>
@@ -253,8 +296,8 @@ Anthropic message storage details
253296
<Card title="Message meta" icon="tag" href="/store/messages/special/message-meta">
254297
Working with message metadata
255298
</Card>
256-
<Card title="Mid-term State" icon="eye" href="/observe/agent_tasks">
257-
Monitor agent tasks and mid-term state
299+
<Card title="Long-term Skill" icon="brain" href="/learn/quick">
300+
Learn skills from agent sessions automatically
258301
</Card>
259302
<Card title="Dashboard" icon="chart-simple" href="/observe/dashboard">
260303
View all interactions

docs/learn/custom-memory.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
title: Custom Memory Algorithms
2+
title: Custom Skills for Long-term Memory
33
description: "Define how your agent remembers by writing SKILL.md files"
44
---
55

docs/learn/learning-spaces.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ await client.learningSpaces.delete(space.id);
9898
## Next Steps
9999

100100
<CardGroup cols={2}>
101-
<Card title="What is Long-term Skill?" icon="brain" href="/learn/skill-memory">
101+
<Card title="Long-term Skill" icon="brain" href="/learn/quick">
102102
Understand how long-term skill compares to other approaches
103103
</Card>
104104
<Card title="Agent Skills" icon="sparkles" href="/store/skill">

docs/learn/quick.mdx

Lines changed: 122 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,22 @@
11
---
2-
title: Quickstart
3-
description: "Set up long-term skill for your agent in 3 steps"
2+
title: "What is Long-term Skill"
3+
description: "Persistent agent memory stored as structured skill files — filesystem-compatible, configurable, and human-readable"
44
---
55

6-
Create a learning space, run your agent, and Acontext automatically builds long-term skills from completed tasks.
6+
Long-term skill is Acontext's approach to persistent agent memory: your agents store memory as **skill files** — plain markdown organized by configurable schemas you control.
7+
8+
```
9+
Session messages ──► Task extraction
10+
└► Learner ──► Skill files
11+
┌─────────────────────┘
12+
13+
social-contacts/
14+
├── SKILL.md (your schema)
15+
├── alice-chen.md (learner-created)
16+
└── bob-martinez.md (learner-created)
17+
```
18+
19+
## Quickstart
720

821
<Steps>
922
<Step title="Create a learning space and run a session">
@@ -48,7 +61,7 @@ await client.sessions.storeMessage(session.id, { role: "user", content: "My name
4861
</CodeGroup>
4962

5063
<Note>
51-
Call `.learn()` before the agent runs. When tasks complete during the session, Acontext automatically picks them up for learning.
64+
Call `.learn()` before the agent runs. When [tasks](/observe/agent_tasks) complete during the session, Acontext automatically picks them up for learning. A **task** is a unit of work the agent completes — Acontext extracts them from session messages automatically.
5265
</Note>
5366
</Step>
5467

@@ -115,16 +128,117 @@ for (const skill of skills) {
115128
}
116129
```
117130
</CodeGroup>
131+
</Step>
132+
133+
<Step title="Use learned skills in your agent">
134+
135+
Give your agent access to the learned skills via [Skill Content Tools](/tool/skill_tools). The agent can then look up what it learned in previous sessions:
136+
137+
<CodeGroup>
138+
```python Python
139+
from acontext.agent.skill import SKILL_TOOLS
140+
from openai import OpenAI
141+
import json
142+
143+
openai_client = OpenAI()
144+
145+
# Get skill IDs from the learning space
146+
skills = client.learning_spaces.list_skills(space.id)
147+
skill_ids = [s.id for s in skills]
148+
149+
# Give the agent access to those skills
150+
ctx = SKILL_TOOLS.format_context(client, skill_ids)
151+
tools = SKILL_TOOLS.to_openai_tool_schema()
152+
153+
messages = [
154+
{"role": "system", "content": f"You have access to skills from past sessions.\n\n{ctx.get_context_prompt()}"},
155+
{"role": "user", "content": "Do you know my name?"}
156+
]
157+
158+
while True:
159+
response = openai_client.chat.completions.create(
160+
model="gpt-4.1", messages=messages, tools=tools
161+
)
162+
message = response.choices[0].message
163+
messages.append(message)
164+
165+
if not message.tool_calls:
166+
print(f"Assistant: {message.content}")
167+
break
168+
169+
for tc in message.tool_calls:
170+
result = SKILL_TOOLS.execute_tool(ctx, tc.function.name, json.loads(tc.function.arguments))
171+
messages.append({"role": "tool", "tool_call_id": tc.id, "content": result})
172+
```
173+
174+
```typescript TypeScript
175+
import { SKILL_TOOLS } from '@acontext/acontext';
176+
import OpenAI from 'openai';
177+
178+
const openai = new OpenAI();
179+
180+
// Get skill IDs from the learning space
181+
const skills = await client.learningSpaces.listSkills(space.id);
182+
const skillIds = skills.map(s => s.id);
183+
184+
// Give the agent access to those skills
185+
const ctx = await SKILL_TOOLS.formatContext(client, skillIds);
186+
const tools = SKILL_TOOLS.toOpenAIToolSchema();
187+
188+
const messages: OpenAI.ChatCompletionMessageParam[] = [
189+
{ role: "system", content: `You have access to skills from past sessions.\n\n${ctx.getContextPrompt()}` },
190+
{ role: "user", content: "Do you know my name?" },
191+
];
192+
193+
while (true) {
194+
const response = await openai.chat.completions.create({
195+
model: "gpt-4.1",
196+
messages,
197+
tools,
198+
});
199+
const message = response.choices[0].message;
200+
messages.push(message);
201+
202+
if (!message.tool_calls) {
203+
console.log(`Assistant: ${message.content}`);
204+
break;
205+
}
206+
207+
for (const tc of message.tool_calls) {
208+
const result = await SKILL_TOOLS.executeTool(ctx, tc.function.name, JSON.parse(tc.function.arguments));
209+
messages.push({ role: "tool", tool_call_id: tc.id, content: result });
210+
}
211+
}
212+
```
213+
</CodeGroup>
214+
118215
</Step>
119216
</Steps>
120217

218+
## Why Skill Files?
219+
220+
<Accordion title="Comparison with other memory approaches">
221+
222+
| | Long-term Skill (Acontext) | Vector Store | Knowledge Graph | Plain-text Files |
223+
|--|--|--|--|--|
224+
| Storage format | Markdown files | Embeddings | Nodes & edges | Text files |
225+
| Human-readable | Yes | No | Partially | Partially |
226+
| Configurable schema | Yes (SKILL.md) | No | Complex upfront | No |
227+
| Filesystem-native | Yes | No | No | Yes |
228+
| Version controllable | Yes | No | No | No |
229+
230+
</Accordion>
231+
121232
## Next Steps
122233

123-
<CardGroup cols={2}>
124-
<Card title="What is Long-term Skill?" icon="brain" href="/learn/skill-memory">
125-
Understand how long-term skill compares to other approaches
234+
<CardGroup cols={3}>
235+
<Card title="Custom Skills" icon="sparkles" href="/learn/custom-memory">
236+
Define your own memory schemas with SKILL.md
126237
</Card>
127-
<Card title="Learning Spaces" icon="sparkles" href="/learn/learning-spaces">
238+
<Card title="Learning Spaces" icon="brain" href="/learn/learning-spaces">
128239
Default skills, custom skills, and managing learning spaces
129240
</Card>
241+
<Card title="Skill Content Tools" icon="wand-magic-sparkles" href="/tool/skill_tools">
242+
Full reference for the skill reading tools
243+
</Card>
130244
</CardGroup>

docs/learn/skill-memory.mdx

Lines changed: 0 additions & 56 deletions
This file was deleted.

docs/quick.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ Build a compact context for agents in one API call
211211
Store and manage files and artifacts in Acontext
212212
</Card>
213213

214-
<Card title="Long-term Skill" icon="brain" href="/learn/skill-memory">
214+
<Card title="Long-term Skill" icon="brain" href="/learn/quick">
215215
Understand how long-term skills work
216216
</Card>
217217

src/client/acontext-py/src/acontext/resources/async_skills.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,15 @@
44

55
import json
66
from collections.abc import Mapping
7+
from pathlib import Path
78
from typing import Any, BinaryIO, cast
89

10+
import httpx
11+
912
from .._utils import build_params
1013
from ..client_types import AsyncRequesterProtocol
1114
from ..types.skill import (
15+
DownloadSkillResp,
1216
DownloadSkillToSandboxResp,
1317
GetSkillFileResp,
1418
ListSkillsOutput,
@@ -135,6 +139,52 @@ async def get_file(
135139
data = await self._requester.request("GET", endpoint, params=params)
136140
return GetSkillFileResp.model_validate(data)
137141

142+
async def download(
143+
self,
144+
*,
145+
skill_id: str,
146+
path: str,
147+
) -> DownloadSkillResp:
148+
"""Download all files from a skill to a local directory.
149+
150+
Recursively downloads every file in the skill's file_index,
151+
preserving the directory structure.
152+
153+
Args:
154+
skill_id: The UUID of the skill.
155+
path: Local directory path to download files into.
156+
157+
Returns:
158+
DownloadSkillResp with skill name, description, resolved dir_path,
159+
and list of downloaded file paths.
160+
"""
161+
skill = await self.get(skill_id)
162+
dest = Path(path).resolve()
163+
dest.mkdir(parents=True, exist_ok=True)
164+
165+
downloaded: list[str] = []
166+
for fi in skill.file_index:
167+
resp = await self.get_file(skill_id=skill_id, file_path=fi.path)
168+
file_dest = dest / fi.path
169+
file_dest.parent.mkdir(parents=True, exist_ok=True)
170+
171+
if resp.content is not None:
172+
file_dest.write_text(resp.content.raw, encoding="utf-8")
173+
elif resp.url is not None:
174+
async with httpx.AsyncClient() as http:
175+
r = await http.get(resp.url)
176+
r.raise_for_status()
177+
file_dest.write_bytes(r.content)
178+
179+
downloaded.append(fi.path)
180+
181+
return DownloadSkillResp(
182+
name=skill.name,
183+
description=skill.description,
184+
dir_path=str(dest),
185+
files=downloaded,
186+
)
187+
138188
async def download_to_sandbox(
139189
self,
140190
*,

0 commit comments

Comments
 (0)