Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,41 @@
## v0.8.34 - 2025-11-28

### Features
- Add LangGraph 2.0 checkpoints table migration
- Add dev and prod docker image tags for releases
- Keep short memory only 90 days
- Add daily scheduled task to clean up old LangGraph checkpoints, writes, and blobs
- Team model support
- Add draft functionality and manager module
- Third party S3 support
- Autonomous use internal service to chat
- Agent testing capabilities
- Move checker to core

### Fixes
- Reorder checkpoint migration steps to drop columns after pk update
- Cache checkpointer
- Improve checkpointer clean
- Clean old generator model
- Cache by agent deploy
- Change node to middleware
- Fix astream bug
- Add basedpyright to llm.md

### Refactoring
- Migrate checkpointer to shallow saver implementation
- Migrate langchain agent middleware
- Move s3 to clients

### Chores
- Remove EKS deployment steps from CI workflow
- Disable kubectl deployments in build workflow
- Disable autonomous, telegram, and checker deployments in testnet-dev
- Remove x402 server
- Upgrade dependencies (uv sync --upgrade)

**Full Changelog**: https://github.com/crestalnetwork/intentkit/compare/v0.8.33...v0.8.34

## v0.8.33 - 2025-11-14

### Bug Fixes
Expand Down
6 changes: 5 additions & 1 deletion LLM.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ IntentKit is an autonomous agent framework that enables creation and management
- API server testing in `tests/api/`
- Skill integration testing in `tests/skills/`

5. **Frontend** (`frontend/`)
- The frontend/ folder contains the Next.js application for managing agents.
- See `intentkit/frontend/AGENTS.md` for detailed architecture and development guidelines.

## Technology Stack
- Package manager: uv
- Virtual environment: .venv, please use `source .venv/bin/activate` at least once to active virtual environment before running any command.
Expand All @@ -39,7 +43,7 @@ IntentKit is an autonomous agent framework that enables creation and management
- API framework: fastapi, Doc in https://fastapi.tiangolo.com/
- DB ORM: SQLAlchemy 2.0, please check the 2.0 api for use, do not use the legacy way. Doc in https://docs.sqlalchemy.org/en/20/
- Model: Pydantic V2, Also be careful not to use the obsolete V1 interface. Doc in https://docs.pydantic.dev/latest/
- Testing Framework: pytest
- Testing Framework: pytest, run `pytest` after your final edit.

## Rules

Expand Down
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,6 @@ The project is divided into the core package and the application:
- [checker.py](app/checker.py): Health and credit checking logic
- [readonly.py](app/readonly.py): Readonly entrypoint
- [scheduler.py](app/scheduler.py): Background task scheduler
- [singleton.py](app/singleton.py): Singleton agent manager
- [telegram.py](app/telegram.py): Telegram integration
- [twitter.py](app/twitter.py): Twitter integration

Expand Down
17 changes: 7 additions & 10 deletions app/admin/__init__.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
from app.admin.api import admin_router, admin_router_readonly
from app.admin.credit import credit_router, credit_router_readonly
from app.admin.api import admin_router
from app.admin.credit import credit_router
from app.admin.health import health_router
from app.admin.metadata import metadata_router_readonly
from app.admin.schema import schema_router_readonly
from app.admin.user import user_router, user_router_readonly
from app.admin.metadata import metadata_router
from app.admin.schema import schema_router
from app.admin.user import user_router

__all__ = [
"admin_router",
"admin_router_readonly",
"health_router",
"schema_router_readonly",
"schema_router",
"credit_router",
"credit_router_readonly",
"metadata_router_readonly",
"metadata_router",
"user_router",
"user_router_readonly",
"agent_generator_router",
Copy link

Copilot AI Dec 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The name 'agent_generator_router' is exported by all but is not defined.

Suggested change
"agent_generator_router",

Copilot uses AI. Check for mistakes.
]
11 changes: 5 additions & 6 deletions app/admin/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,12 @@

from app.auth import verify_admin_jwt

admin_router_readonly = APIRouter()
admin_router = APIRouter()

logger = logging.getLogger(__name__)


@admin_router_readonly.post(
@admin_router.post(
"/agent/validate",
tags=["Agent"],
status_code=204,
Expand Down Expand Up @@ -98,7 +97,7 @@ async def validate_agent_create(
return Response(status_code=204)


@admin_router_readonly.post(
@admin_router.post(
"/agents/{agent_id}/validate",
tags=["Agent"],
status_code=204,
Expand Down Expand Up @@ -331,7 +330,7 @@ async def override_agent_endpoint(
)


@admin_router_readonly.get(
@admin_router.get(
"/agents",
tags=["Agent"],
dependencies=[Depends(verify_admin_jwt)],
Expand Down Expand Up @@ -365,7 +364,7 @@ async def get_agents(db: AsyncSession = Depends(get_db)) -> list[AgentResponse]:
]


@admin_router_readonly.get(
@admin_router.get(
"/agents/{agent_id}",
tags=["Agent"],
dependencies=[Depends(verify_admin_jwt)],
Expand Down Expand Up @@ -498,7 +497,7 @@ async def clean_memory(
)


@admin_router_readonly.get(
@admin_router.get(
"/agents/{agent_id}/export",
tags=["Agent"],
operation_id="export_agent",
Expand Down
17 changes: 8 additions & 9 deletions app/admin/credit.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@
logger = logging.getLogger(__name__)

credit_router = APIRouter(prefix="/credit", tags=["Credit"])
credit_router_readonly = APIRouter(prefix="/credit", tags=["Credit"])


# ===== Models =====
Expand Down Expand Up @@ -362,7 +361,7 @@ async def get_agent_statistics(
return await agent_statistics.get_agent_statistics(agent_id, session=db)


@credit_router_readonly.get(
@credit_router.get(
"/users/{user_id}/events",
response_model=CreditEventsResponse,
operation_id="list_user_events",
Expand Down Expand Up @@ -437,7 +436,7 @@ async def update_event_note(
)


@credit_router_readonly.get(
@credit_router.get(
"/event/users/{user_id}/expense",
response_model=CreditEventsResponse,
operation_id="list_user_expense_events",
Expand Down Expand Up @@ -478,7 +477,7 @@ async def list_user_expense_events(
)


@credit_router_readonly.get(
@credit_router.get(
"/transactions",
response_model=CreditTransactionsResponse,
operation_id="list_transactions",
Expand Down Expand Up @@ -602,7 +601,7 @@ async def list_transactions(
)


@credit_router_readonly.get(
@credit_router.get(
"/event/users/{user_id}/income",
response_model=CreditEventsResponse,
operation_id="list_user_income_events",
Expand Down Expand Up @@ -646,7 +645,7 @@ async def list_user_income_events(
)


@credit_router_readonly.get(
@credit_router.get(
"/event/agents/{agent_id}/income",
response_model=CreditEventsResponse,
operation_id="list_agent_income_events",
Expand Down Expand Up @@ -686,7 +685,7 @@ async def list_agent_income_events(
)


@credit_router_readonly.get(
@credit_router.get(
"/event",
response_model=CreditEvent,
operation_id="fetch_credit_event_by_upstream_tx_id",
Expand All @@ -712,7 +711,7 @@ async def fetch_credit_event(
return await fetch_credit_event_by_upstream_tx_id(db, upstream_tx_id)


@credit_router_readonly.get(
@credit_router.get(
"/events/{event_id}",
response_model=CreditEvent,
operation_id="fetch_credit_event_by_id",
Expand Down Expand Up @@ -774,7 +773,7 @@ async def fetch_credit_event_by_id_endpoint(
return event


@credit_router_readonly.get(
@credit_router.get(
"/events",
operation_id="list_credit_events",
summary="List Credit Events",
Expand Down
6 changes: 3 additions & 3 deletions app/admin/metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from intentkit.models.skill import Skill

# Create a readonly router for metadata endpoints
metadata_router_readonly = APIRouter(tags=["Metadata"])
metadata_router = APIRouter(tags=["Metadata"])


class LLMModelInfoWithProviderName(LLMModelInfo):
Expand All @@ -17,7 +17,7 @@ class LLMModelInfoWithProviderName(LLMModelInfo):
provider_name: str


@metadata_router_readonly.get(
@metadata_router.get(
"/metadata/skills",
response_model=list[Skill],
summary="Get all skills",
Expand All @@ -37,7 +37,7 @@ async def get_skills(db: AsyncSession = Depends(get_db)):
raise


@metadata_router_readonly.get(
@metadata_router.get(
"/metadata/llms",
response_model=list[LLMModelInfoWithProviderName],
summary="Get all LLM models",
Expand Down
10 changes: 4 additions & 6 deletions app/admin/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,13 @@
logger = logging.getLogger(__name__)

# Create readonly router
schema_router_readonly = APIRouter()
schema_router = APIRouter()

# Get the project root directory
PROJECT_ROOT = Path(__file__).parent.parent.parent


@schema_router_readonly.get(
"/schema/agent", tags=["Schema"], operation_id="get_agent_schema"
)
@schema_router.get("/schema/agent", tags=["Schema"], operation_id="get_agent_schema")
async def get_agent_schema(db: AsyncSession = Depends(get_db)) -> JSONResponse:
"""Get the JSON schema for Agent model with all $ref references resolved.

Expand All @@ -41,7 +39,7 @@ async def get_agent_schema(db: AsyncSession = Depends(get_db)) -> JSONResponse:
)


@schema_router_readonly.get(
@schema_router.get(
"/skills/{skill}/schema.json",
tags=["Schema"],
operation_id="get_skill_schema",
Expand Down Expand Up @@ -81,7 +79,7 @@ async def get_skill_schema(
return JSONResponse(content=schema, media_type="application/json")


@schema_router_readonly.get(
@schema_router.get(
"/skills/{skill}/{icon_name}.{ext}",
tags=["Schema"],
operation_id="get_skill_icon",
Expand Down
3 changes: 1 addition & 2 deletions app/admin/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,9 @@
logger = logging.getLogger(__name__)

user_router = APIRouter(prefix="/users", tags=["User"])
user_router_readonly = APIRouter(prefix="/users", tags=["User"])


@user_router_readonly.get(
@user_router.get(
"/{user_id}",
response_model=User,
operation_id="get_user",
Expand Down
27 changes: 9 additions & 18 deletions app/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,21 +31,17 @@

from app.admin import (
admin_router,
admin_router_readonly,
credit_router,
credit_router_readonly,
health_router,
metadata_router_readonly,
schema_router_readonly,
metadata_router,
schema_router,
user_router,
user_router_readonly,
)
from app.entrypoints.agent_api import router_ro as agent_api_ro
from app.entrypoints.agent_api import router_rw as agent_api_rw
from app.entrypoints.agent_api import agent_api_router
from app.entrypoints.openai_compatible import openai_router
from app.entrypoints.web import chat_router, chat_router_readonly
from app.services.twitter.oauth2 import router as twitter_oauth2_router
from app.services.twitter.oauth2_callback import router as twitter_callback_router
from app.entrypoints.web import chat_router
from app.services.twitter.oauth2 import twitter_oauth2_router
from app.services.twitter.oauth2_callback import twitter_callback_router

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -120,8 +116,7 @@ def _load_agent_api_docs() -> str:
)

# Add routers to the Agent API sub-application
agent_app.include_router(agent_api_rw)
agent_app.include_router(agent_api_ro)
agent_app.include_router(agent_api_router)
agent_app.include_router(openai_router)


Expand Down Expand Up @@ -190,15 +185,11 @@ async def lifespan(app: FastAPI):
app.mount("/v1", agent_app)

app.include_router(chat_router)
app.include_router(chat_router_readonly)
app.include_router(admin_router)
app.include_router(admin_router_readonly)
app.include_router(metadata_router_readonly)
app.include_router(metadata_router)
app.include_router(credit_router)
app.include_router(credit_router_readonly)
app.include_router(schema_router_readonly)
app.include_router(schema_router)
app.include_router(user_router)
app.include_router(user_router_readonly)
app.include_router(core_router)
app.include_router(twitter_callback_router)
app.include_router(twitter_oauth2_router)
Expand Down
1 change: 0 additions & 1 deletion app/auth/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ async def verify_admin_jwt(
or host == "127.0.0.1"
or host == "intent-api"
or host == "intent-readonly"
or host == "intent-singleton"
):
return ""

Expand Down
Loading
Loading