Repository-based tools are standalone projects that can be published and shared with other Compozy users. You can create tools using either TypeScript (running on Deno runtime) or Python, which can be compiled into platform-specific binaries for efficient distribution.
Repository Structure
my-tool/
├── deno.json # Deno configuration and tasks
├── manifest.yaml # Tool metadata and schema definitions
├── README.md # Documentation
├── src/ # Source code directory
│ ├── index.ts # Main entry point
│ └── lib/ # Additional modules
├── tests/ # Test files
│ └── index.test.ts
├── dist/ # Compiled binaries
└── my-tool
my-tool/
├── deno.json # Deno configuration and tasks
├── manifest.yaml # Tool metadata and schema definitions
├── README.md # Documentation
├── src/ # Source code directory
│ ├── index.ts # Main entry point
│ └── lib/ # Additional modules
├── tests/ # Test files
│ └── index.test.ts
├── dist/ # Compiled binaries
└── my-tool
my-tool/
├── pyproject.toml # Python project configuration
├── manifest.yaml # Tool metadata and schema definitions
├── src/ # Source code directory
│ ├── main.py # Main entry point
│ └── lib/ # Additional modules
├── tests/ # Test files
│ └── test_main.py
├── README.md # Documentation
└── dist/ # Compiled binaries
└── my-tool
Project Configuration
The deno.json
file configures your development environment and build process:
{
"tasks" : {
"dev" : "deno run --allow-read --allow-net src/index.ts" ,
"test" : "deno test --allow-read --allow-net tests/" ,
"compile" : "deno compile --allow-read --allow-net --output dist/stock-price src/index.ts" ,
},
}
The compile
task is required in your deno.json
file. Compozy uses this task to compile your tool into a platform-specific binary during the publishing process.
The deno.json
file configures your development environment and build process:
{
"tasks" : {
"dev" : "deno run --allow-read --allow-net src/index.ts" ,
"test" : "deno test --allow-read --allow-net tests/" ,
"compile" : "deno compile --allow-read --allow-net --output dist/stock-price src/index.ts" ,
},
}
The compile
task is required in your deno.json
file. Compozy uses this task to compile your tool into a platform-specific binary during the publishing process.
The pyproject.toml
file configures your Python project:
[project]
name = "stock-price"
version = "1.0.0"
description = "Fetch real-time stock prices from various financial markets"
requires-python = ">=3.8"
dependencies = [
"stock-api" ,
"pydantic"
]
[project.optional-dependencies]
test = [ "pytest" , "pytest-asyncio" ]
[tool.pytest.ini_options]
asyncio_mode = "auto"
Manifest File
The manifest.yaml
defines your tool’s metadata, configuration, and I/O schema. Here’s a comprehensive example:
The type
field is required and must be set to tool
. For Python projects, set main: src/main.py
instead of src/index.ts
.
type : tool
name : stock-price
version : 1.0.0
license : MIT
description : Fetch real-time stock prices from various financial markets
repository : https://github.com/your-org/stock-price
main : src/index.ts # Use src/main.py for Python projects
tags :
- stocks
- finance
author :
name : Your Name
email : your.email@example.com
organization : Your Organization
schema :
config :
type : object
properties :
api_key :
type : string
description : "API key for accessing stock data"
rate_limit :
type : number
description : "Maximum API calls per minute"
default : 60
required : [ api_key ]
input :
type : object
properties :
symbol :
type : string
description : "Stock symbol (e.g., AAPL, GOOGL)"
pattern : "^[A-Z]{1,5}$"
market :
type : string
description : "Stock exchange (e.g., NYSE, NASDAQ)"
enum : [ "NYSE" , "NASDAQ" , "LSE" , "TSE" ]
default : "NYSE"
required : [ symbol ]
output :
type : object
properties :
price :
type : number
description : "Current stock price"
currency :
type : string
description : "Price currency (ISO 4217)"
pattern : "^[A-Z]{3}$"
timestamp :
type : string
description : "Last update timestamp (ISO 8601)"
format : "date-time"
change_24h :
type : number
description : "Price change in the last 24 hours (%)"
required : [ price , currency , timestamp ]
See all 62 lines
Implementation
Your src/index.ts
should implement the schema defined in the manifest:
// You can use imports as usual with Deno
import { StockAPI } from 'npm:stock-api' ;
import { validateInput } from 'jsr:@std/validation' ;
interface Config {
api_key : string ;
rate_limit ?: number ;
}
interface Input {
symbol : string ;
market ?: 'NYSE' | 'NASDAQ' | 'LSE' | 'TSE' ;
}
interface Output {
price : number ;
currency : string ;
timestamp : string ;
change_24h ?: number ;
}
export async function run ( input : Input , config : Config ): Promise < Output > {
// Validate input
validateInput ( input );
// Initialize API with rate limiting
const api = new StockAPI ({
apiKey: config . api_key ,
rateLimit: config . rate_limit ?? 60
});
// Fetch stock data
const data = await api . getPrice ( input . symbol , input . market );
return {
price: data . price ,
currency: data . currency ,
timestamp: new Date (). toISOString (),
change_24h: data . change_24h
};
}
Your src/index.ts
should implement the schema defined in the manifest:
// You can use imports as usual with Deno
import { StockAPI } from 'npm:stock-api' ;
import { validateInput } from 'jsr:@std/validation' ;
interface Config {
api_key : string ;
rate_limit ?: number ;
}
interface Input {
symbol : string ;
market ?: 'NYSE' | 'NASDAQ' | 'LSE' | 'TSE' ;
}
interface Output {
price : number ;
currency : string ;
timestamp : string ;
change_24h ?: number ;
}
export async function run ( input : Input , config : Config ): Promise < Output > {
// Validate input
validateInput ( input );
// Initialize API with rate limiting
const api = new StockAPI ({
apiKey: config . api_key ,
rateLimit: config . rate_limit ?? 60
});
// Fetch stock data
const data = await api . getPrice ( input . symbol , input . market );
return {
price: data . price ,
currency: data . currency ,
timestamp: new Date (). toISOString (),
change_24h: data . change_24h
};
}
Your src/main.py
should implement the schema defined in the manifest:
from typing import TypedDict, Optional
from datetime import datetime
from stock_api import StockAPI
from validation import validate_input
class Config ( TypedDict ):
api_key: str
rate_limit: Optional[ int ]
class Input ( TypedDict ):
symbol: str
market: Optional[ str ] # 'NYSE' | 'NASDAQ' | 'LSE' | 'TSE'
class Output ( TypedDict ):
price: float
currency: str
timestamp: str
change_24h: Optional[ float ]
async def run ( input : Input, config : Config) -> Output:
# Validate input
validate_input( input )
# Initialize API with rate limiting
api = StockAPI(
api_key =config[ 'api_key' ],
rate_limit =config.get( 'rate_limit' , 60 )
)
# Fetch stock data
data = await api.get_price( input [ 'symbol' ], input .get( 'market' ))
return {
'price' : data.price,
'currency' : data.currency,
'timestamp' : datetime.now().isoformat(),
'change_24h' : data.change_24h
}
Publishing Process
Prepare Your Repository
Initialize a GitHub repository
Set up CI/CD workflows for testing and releases
Include comprehensive documentation in README.md
Quality Checks
Write unit tests covering main functionality
Add integration tests for API interactions
Ensure proper error handling and input validation
Version and Release
Use semantic versioning (MAJOR.MINOR.PATCH)
Create GitHub releases with detailed changelogs
Tag releases (e.g., v1.0.0
)
Build and Distribution
# Compile for all platforms
deno task compile
# Compile for all platforms
deno task compile
# Build Python package
python -m build
Submit to Registry
Once your tool is ready for distribution:
# Login to Compozy CLI
compozy login
# Submit your tool
compozy publish
After submission, our team will review your tool to ensure it meets our quality and security standards. You’ll receive notifications about the review process and when your tool is approved and listed in the registry.
Make sure your repository is public and the latest release tag matches the version in your manifest.yaml before publishing.