원클릭으로
init-tower-app
Create a Tower app — either a hello-world scaffold (greenfield) or a wrapper around existing Python pipeline code.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Create a Tower app — either a hello-world scaffold (greenfield) or a wrapper around existing Python pipeline code.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Create a dlt REST API pipeline to run as a Tower app. Use for the rest_api core source, or any generic REST/HTTP API source. Not for sql_database or filesystem sources.
Explore and profile loaded data from a data consumer perspective. Scores 5 dimensions (completeness, freshness, consistency, queryability, discoverability). Absorbs validate-data. Modes — PROFILE (automated after load), VALIDATE (cross-reference against source), EXPLORE (interactive queries). Routes issues to responsible persona.
Debug and inspect a Tower app after running it. Supports dlt pipelines, ASGI apps, and plain Python scripts. Use after a run (success or failure) to inspect logs, diagnose errors, and fix issues.
Find a dlt destination for a given storage provider. Use when the user asks about a destination, wants to find a connector, or asks to implement a pipeline for a specific data destination.
Find a dlt source for a given API or data provider. Use when the user asks about a source, wants to find a connector, or asks to implement a pipeline for a specific data source.
Detect existing project stack, learn conventions from code, and produce a project profile. Run before other skills to give them richer context, or let skills invoke it automatically when no profile exists.
| name | init-tower-app |
| description | Create a Tower app — either a hello-world scaffold (greenfield) or a wrapper around existing Python pipeline code. |
| allowed-tools | ["Read","Write","Edit","Bash","Glob","Grep","AskUserQuestion","mcp__tower-mcp__tower_teams_list","mcp__tower-mcp__tower_teams_switch","mcp__tower-mcp__tower_file_generate","mcp__tower-mcp__tower_file_update","mcp__tower-mcp__tower_file_validate","mcp__tower-mcp__tower_file_read","mcp__tower-mcp__tower_run_local","mcp__tower-mcp__tower_apps_logs","mcp__tower-mcp__tower_apps_show"] |
Create a Tower app. Two modes: SCAFFOLD (greenfield) or WRAP (existing Python code).
Read .tower/project-profile.md if it exists.
empty (Towerfile already exists): the app is already initialized. Report DONE immediately: "Tower app already exists ({app_name}). No scaffolding needed."empty: check for existing scripts (below).Detect existing Python scripts:
If no Towerfile exists, scan for Python files that could be Tower apps:
find . -name "*.py" -not -path "./.venv/*" -not -path "./__pycache__/*" -not -name "setup.py" -not -name "conftest.py" -not -name "noxfile.py" 2>/dev/null | head -20
If matches are found:
dlt.pipeline (dlt pipeline)Starlette or FastAPI or app = (ASGI app)if __name__ (any Python script)$EXISTING_SCRIPT.dlt (has dlt imports), asgi (has Starlette/FastAPI), or python (everything else).If no matches are found:
Run ls -la to see the current state before scaffolding.
Check if uv is available. If not, install it with pip install uv and then activate the venv.
If uv is available, and the folder snapshot shows that we're already in an active uv project, continue.
If the folder is still not a uv project, initialize it with uv init and activate the venv.
Run uv add tower>=0.1.0 to install the latest version of Tower. This ensures we have the latest features and bug fixes.
task.py entry point (mode-dependent)SCAFFOLD mode (no existing scripts):
Create a task.py file with the following content:
import tower
if __name__ == "__main__":
print(f"Hello from Tower version {dir(tower)}")
WRAP mode (existing script at $EXISTING_SCRIPT):
Do NOT delete, rename, or restructure the user's existing files.
If $EXISTING_SCRIPT is already named task.py: skip this step entirely — the entry point already exists.
Otherwise, create a thin task.py wrapper based on the detected app type:
dlt or Python script with a main() function — prefer a direct import:
"""Tower entry point — wraps existing script."""
from $MODULE import main
if __name__ == "__main__":
main()
ASGI app (exports an app object like app = FastAPI() or app = Starlette()):
Tower natively serves ASGI apps. Create a task.py that re-exports the app:
"""Tower entry point — wraps existing ASGI app."""
from $MODULE import app # noqa: F401
Tower will detect the app object and serve it automatically. No uvicorn startup needed.
No clear callable entry point — use subprocess:
"""Tower entry point — wraps existing script."""
import subprocess
import sys
if __name__ == "__main__":
sys.exit(subprocess.call([sys.executable, "$EXISTING_SCRIPT"]))
Replace $MODULE and $EXISTING_SCRIPT with actual values (e.g., from pipeline import main).
CRITICAL: ALWAYS use tower-mcp server for ALL Tower operations.
Check whether the user is logged into Tower and whether they are on the right team. Use the tower_teams_list tool from the tower-mcp server to list teams and confirm the right one is active. If the user wants to switch teams, they can do so with tower_teams_switch MCP tool.
CRITICAL: Use tower-mcp, NOT CLI commands.
Check whether the Towerfile lists source files explicitly. If that's the case, use the tower_file_update tool from tower-mcp server to replace the list with a wildcard (*), then use tower_file_validate to verify the file.
WRAP mode: The wildcard * is strongly preferred since it covers both task.py and $EXISTING_SCRIPT (plus any local modules the script imports).
After generating or updating the Towerfile, use tower_file_update to add a DLT_DATA_DIR environment variable parameter with a default value of /tmp. This ensures dlt has a writable data directory in all Tower runtime environments.
CRITICAL: Use tower-mcp for running apps, NOT uv run tower CLI.
Run the Tower app locally using the tower_run_local tool from the tower-mcp server. Use tower_apps_logs to inspect output if needed.
ConfigFieldMissingException), that counts as SUCCESS for this step — it means the Tower wrapper structure is correct. Report what credentials or setup the user needs next.Report one of these status codes when the skill finishes:
| Status | Meaning |
|---|---|
| DONE | App created. SCAFFOLD: tower_run_local prints Tower version. WRAP: tower_run_local executes existing script/serves ASGI app (or fails on credentials only). |
| DONE_WITH_CONCERNS | App runs but with warnings (e.g. outdated Tower version, team mismatch, missing credentials in WRAP mode) |
| BLOCKED | Cannot proceed — uv not available and install failed, or Tower login/team check failed |
| NEEDS_CONTEXT | User must clarify team selection or project directory before continuing |
uv not available or install fails:
Run pip install uv. If that also fails (e.g. no pip), check whether Python is available with python3 --version. Suggest the user install uv manually: curl -LsSf https://astral.sh/uv/install.sh | sh. Status: BLOCKED if unresolvable.
tower_teams_list fails (MCP not available or auth error):
Verify the tower-mcp server is running. Ask the user to confirm they are logged into Tower. Do NOT fall back to CLI commands. Status: BLOCKED.
tower_file_validate fails:
Read the validation error message. Common causes: missing task.py reference, invalid YAML syntax, unsupported Towerfile fields. Fix the Towerfile and re-validate. If the error is unclear, regenerate with tower_file_generate and try again.
tower_run_local fails on the hello-world script:
Check tower_apps_logs for the error. If it is a dependency issue, run uv add tower>=0.1.0 again. If it is a permissions or auth issue, revisit team selection.